libspe2-2.2.80-95/0000755000175100017510000000000010762264436013006 5ustar arthurarthurlibspe2-2.2.80-95/tests/0000755000175100017510000000000010707604274014145 5ustar arthurarthurlibspe2-2.2.80-95/tests/testmap1.c0000644000175100017510000000123310600243027016031 0ustar arthurarthur#include #include #include "libspe2.h" int main(void) { spe_context_ptr_t ctx; int flags = SPE_MAP_PS; struct spe_mfc_command_area * mfc_cmd_area; struct spe_spu_control_area * spu_control_area; unsigned int MFC_LSA; unsigned int status; printf("starting ..\n"); ctx = spe_context_create(flags, NULL); mfc_cmd_area = spe_ps_area_get(ctx, SPE_MFC_COMMAND_AREA); printf("mfc_cmd_area is: %p\n", mfc_cmd_area); MFC_LSA = mfc_cmd_area->MFC_LSA; spu_control_area = spe_ps_area_get(ctx, SPE_CONTROL_AREA); status = spu_control_area->SPU_Status; spe_context_destroy(ctx); printf("%d done\n", status); printf("%d done\n", MFC_LSA); } libspe2-2.2.80-95/tests/testsingle.c0000644000175100017510000000133510602503134016457 0ustar arthurarthur#include #include #include #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("hello"); if (!program) { perror("spe_open_image"); 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; } libspe2-2.2.80-95/tests/testsinglemini.c0000644000175100017510000000064010600243027017332 0ustar arthurarthur #include #include "libspe2.h" int main() { spe_context_ptr_t ctx; unsigned int flags = 0; unsigned int entry = SPE_DEFAULT_ENTRY; void * argp = NULL; void * envp = NULL; spe_program_handle_t * program; program = spe_image_open("hello"); ctx = spe_context_create(flags, 0); spe_program_load(ctx, program); spe_context_run(ctx, &entry, flags, argp, envp, NULL); spe_context_destroy(ctx); } libspe2-2.2.80-95/tests/testevent1.c0000644000175100017510000000324710600243027016404 0ustar arthurarthur/** * Scenario 1: Portable Usage */ #include #define MAX_EVENTS 8 #define SIZE 8 #define COUNT 1 int main() { int i, rc, event_count; spe_event_handler_ptr_t evhandler; spe_event_unit_t event; spe_context_ptr_t ctx; spe_event_unit_t events[MAX_EVENTS]; spe_stop_info_t stop_info; spe_program_handle_t * program; unsigned int entry = SPE_DEFAULT_ENTRY; void * argp = NULL; void * envp = NULL; /* Create a context. */ ctx = spe_context_create(SPE_EVENTS_ENABLE, NULL); if (ctx == NULL) { perror("spe_context_create"); return -2; } /* load the program. */ program = spe_image_open("hello"); if (!program) { perror("spe_open_image"); return -1; } if (spe_program_load(ctx, program)) { perror("spe_program_load"); return -3; } /* Create a handle. */ evhandler = spe_event_handler_create(); /* Register events. */ event.events = SPE_EVENT_SPE_STOPPED; event.spe = ctx; rc = spe_event_handler_register(evhandler, &event); /* run the context */ rc = spe_context_run(ctx, &entry, 0, argp, envp, &stop_info); if (rc < 0) perror("spe_context_run"); /* Get events. */ event_count = spe_event_wait(evhandler, events, MAX_EVENTS, 0); printf("event_count: %d\n", event_count); /* Handle events. */ for (i = 0; i < event_count; i++) { printf("event %d: %d\n", i, events[i].events); if (events[i].events & SPE_EVENT_SPE_STOPPED) { printf("received SPE_EVENT_SPE_STOPPED\n"); rc = spe_stop_info_read(events[i].spe, &stop_info); printf("exit_code: %d\n", stop_info.result.spe_exit_code); } } /* Destroy the handle. */ spe_event_handler_destroy(evhandler); /* Destroy the context. */ spe_context_destroy(ctx); return 0; } libspe2-2.2.80-95/tests/testinfo.c0000644000175100017510000000102410600243027016124 0ustar arthurarthur #include #include "libspe2.h" int main(void) { int no, nocpus , i; nocpus = spe_cpu_info_get(SPE_COUNT_PHYSICAL_CPU_NODES, -2); printf("-2 ==> %d (%d)\n", nocpus, errno); nocpus = spe_cpu_info_get(SPE_COUNT_PHYSICAL_CPU_NODES, -1); printf("-1 ==> %d (%d)\n", nocpus, errno); for (i=-2; i <= nocpus; i++) { no = spe_cpu_info_get(SPE_COUNT_PHYSICAL_SPES, i); printf("%2d ==> %d (%d)\n",i, no, errno); no = spe_cpu_info_get(SPE_COUNT_USABLE_SPES, i); printf("%2d ==> %d (%d)\n",i, no, errno); } } libspe2-2.2.80-95/tests/testpthread.c0000644000175100017510000000234010600243027016622 0ustar arthurarthur #include #include #include #include #include "libspe2.h" struct thread_args { struct spe_context * ctx; void * argp; void * envp; }; void * spe_thread(void * arg); __attribute__((noreturn)) void * spe_thread(void * arg) { int flags = 0; unsigned int entry = SPE_DEFAULT_ENTRY; int rc; spe_program_handle_t * program; struct thread_args * arg_ptr; arg_ptr = (struct thread_args *) arg; program = spe_image_open("hello"); if (!program) { perror("spe_image_open"); pthread_exit(NULL); } if (spe_program_load(arg_ptr->ctx, program)) { perror("spe_program_load"); pthread_exit(NULL); } rc = spe_context_run(arg_ptr->ctx, &entry, flags, arg_ptr->argp, arg_ptr->envp, NULL); if (rc < 0) perror("spe_context_run"); pthread_exit(NULL); } int main() { int thread_id; pthread_t pts; spe_context_ptr_t ctx; struct thread_args t_args; int value = 1; int flags = 0; if (!(ctx = spe_context_create(flags, NULL))) { perror("spe_create_context"); return -2; } t_args.ctx = ctx; t_args.argp = &value; thread_id = pthread_create( &pts, NULL, &spe_thread, &t_args); pthread_join (pts, NULL); spe_context_destroy (ctx); return 0; } libspe2-2.2.80-95/tests/readmbox.c0000644000175100017510000000072710602653464016117 0ustar arthurarthur/* --------------------------------------------------------------- */ /* (C) Copyright 2007 */ /* International Business Machines Corporation, */ /* */ /* All Rights Reserved. */ /* --------------------------------------------------------------- */ #include #include main() { unsigned int data = 0; while (data != 8) { data = spu_read_in_mbox(); printf("SPE received %d\n", data); } return 0; } libspe2-2.2.80-95/tests/testpthreadmini.c0000644000175100017510000000156510600243027017507 0ustar arthurarthur #include #include #include "libspe2.h" struct thread_args { struct spe_context * ctx; void * argp; void * envp; }; void * spe_thread(void * arg) { int flags = 0; unsigned int entry = SPE_DEFAULT_ENTRY; spe_program_handle_t * program; struct thread_args * arg_ptr; arg_ptr = (struct thread_args *) arg; program = spe_image_open("hello"); spe_program_load(arg_ptr->ctx, program); spe_context_run(arg_ptr->ctx, &entry, flags, arg_ptr->argp, arg_ptr->envp, NULL); pthread_exit(NULL); } int main() { int thread_id; pthread_t pts; spe_context_ptr_t ctx; struct thread_args t_args; int value = 1; ctx = spe_context_create(0, NULL); t_args.ctx = ctx; t_args.argp = &value; thread_id = pthread_create( &pts, NULL, &spe_thread, &t_args); pthread_join (pts, NULL); spe_context_destroy (ctx); return 0; } libspe2-2.2.80-95/tests/testlibspe2hello.c0000644000175100017510000000147010600243027017562 0ustar arthurarthur/* --------------------------------------------------------------- */ /* (C) Copyright 2001,2006, */ /* International Business Machines Corporation, */ /* */ /* All Rights Reserved. */ /* --------------------------------------------------------------- */ /* PROLOG END TAG zYx */ #include typedef union { unsigned long long ull; unsigned int vp[2]; } addr64; int main (int speid, addr64 argp, addr64 envp) { printf("\t\tHello World! speid=0x%llx, argp=0x%08x%08x, envp=0x%08x%08x\n", speid, argp.vp[0],argp.vp[1], envp.vp[0],envp.vp[1]); return 0; } libspe2-2.2.80-95/tests/Makefile0000644000175100017510000000316010642456142015602 0ustar arthurarthur#* #* libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS #* Copyright (C) 2005 IBM Corp. #* #* This library is free software; you can redistribute it and/or modify it #* under the terms of the GNU Lesser General Public License as published by #* the Free Software Foundation; either version 2.1 of the License, #* or (at your option) any later version. #* #* This library is distributed in the hope that it will be useful, but #* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY #* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public #* License for more details. #* #* You should have received a copy of the GNU Lesser General Public License #* along with this library; if not, write to the Free Software Foundation, #* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #* TOP=.. include $(TOP)/make.defines CFLAGS += -I$(TOP)/spebase CFLAGS += -I$(TOP)/spethread CFLAGS += -I$(TOP)/spegang CFLAGS += -I$(TOP)/speevent CFLAGS += -I$(TOP) -g LDFLAGS := $(CFLAGS) LDLIBS := -L$(TOP) -lspe2 -lpthread ALL := testsingle testsinglemini hello hellointr\ testmap1 \ testpthread testpthreadmini \ testlibspe2 testlibspe2hello \ testinfo testhandler \ testevent1 testevent2 \ testmbox readmbox all: $(ALL) hello: helloworld.c $(SPU_CC) $(SPU_CFLAGS) -o hello helloworld.c hellointr: hellointr.c $(SPU_CC) $(SPU_CFLAGS) -o hellointr hellointr.c readmbox: readmbox.c $(SPU_CC) $(SPU_CFLAGS) -o readmbox readmbox.c testlibspe2hello: testlibspe2hello.c $(SPU_CC) $(SPU_CFLAGS) -o testlibspe2hello testlibspe2hello.c clean: rm -f $(ALL) libspe2-2.2.80-95/tests/testhandler.c0000644000175100017510000000231510600315611016611 0ustar arthurarthur/* --------------------------------------------------------------- */ /* (C) Copyright 2007 */ /* International Business Machines Corporation, */ /* */ /* All Rights Reserved. */ /* --------------------------------------------------------------- */ #include #include #include #include int local_handler(void *bla, unsigned int npc) { return 0; } int main(void) { int i, rc; void * handler; for (i = -1; i < 257; i++) { handler = spe_callback_handler_query(i); printf("\nquery\t\t%d (%d)\n", i, errno); rc = spe_callback_handler_register(&local_handler, i, SPE_CALLBACK_NEW); printf("register\t%d %d (%d)\n", i, rc, errno); handler = spe_callback_handler_query(i); printf("\nquery\t\t%d (%d)\n", i, errno); rc = spe_callback_handler_deregister(i); printf("deregister\t%d %d (%d)\n", i, rc, errno); handler = spe_callback_handler_query(i); printf("\nquery\t\t%d (%d)\n", i, errno); rc = spe_callback_handler_register(&local_handler, i, SPE_CALLBACK_UPDATE); printf("update\t\t%d %d (%d)\n", i, rc, errno); handler = spe_callback_handler_query(i); printf("\nquery\t\t%d (%d)\n", i, errno); } return 0; } libspe2-2.2.80-95/tests/testevent2.c0000644000175100017510000000476710600243027016415 0ustar arthurarthur #include #include #include #include #include "libspe2.h" #define MAX_EVENTS 8 #define SIZE 8 #define COUNT 1 struct thread_args { struct spe_context * ctx; void * argp; void * envp; }; void * spe_thread(void * arg); __attribute__((noreturn)) void * spe_thread(void * arg) { int flags = 0; unsigned int entry = SPE_DEFAULT_ENTRY; int rc; spe_program_handle_t * program; struct thread_args * arg_ptr; arg_ptr = (struct thread_args *) arg; program = spe_image_open("hellointr"); if (!program) { perror("spe_image_open"); pthread_exit(NULL); } if (spe_program_load(arg_ptr->ctx, program)) { perror("spe_program_load"); pthread_exit(NULL); } rc = spe_context_run(arg_ptr->ctx, &entry, flags, arg_ptr->argp, arg_ptr->envp, NULL); if (rc < 0) perror("spe_context_run"); pthread_exit(NULL); } int main() { int thread_id; int i, rc, event_count; pthread_t pts; spe_context_ptr_t ctx; struct thread_args t_args; int value = 1; int flags = SPE_EVENTS_ENABLE; spe_event_handler_ptr_t evhandler; spe_event_unit_t event; spe_event_unit_t events[MAX_EVENTS]; unsigned int mbox_data[COUNT]; spe_stop_info_t stop_info; int cont; if (!(ctx = spe_context_create(flags, NULL))) { perror("spe_create_context"); return -2; } /* Create a handle. */ evhandler = spe_event_handler_create(); /* Register events. */ event.events = SPE_EVENT_OUT_INTR_MBOX | SPE_EVENT_SPE_STOPPED; event.spe = ctx; rc = spe_event_handler_register(evhandler, &event); /* start pthread */ t_args.ctx = ctx; t_args.argp = &value; thread_id = pthread_create( &pts, NULL, &spe_thread, &t_args); /* Get events. */ cont = 1; while (cont) { event_count = spe_event_wait(evhandler, events, MAX_EVENTS, -1); printf("event_count %d\n", event_count); /* Handle events. */ for (i = 0; i < event_count; i++) { printf("event %d: %d\n", i, events[i].events); if (events[i].events & SPE_EVENT_OUT_INTR_MBOX) { printf("SPE_EVENT_OUT_INTR_MBOX\n"); rc = spe_out_intr_mbox_read(events[i].spe, mbox_data, COUNT, SPE_MBOX_ANY_BLOCKING); } if (events[i].events & SPE_EVENT_SPE_STOPPED) { printf("SPE_EVENT_SPE_STOPPED\n"); rc = spe_stop_info_read(events[i].spe, &stop_info); printf("stop_reason: %d\n", stop_info.stop_reason); cont = 0; } } } pthread_join (pts, NULL); /* Destroy the handle. */ spe_event_handler_destroy(evhandler); /* Destroy the context. */ spe_context_destroy (ctx); return 0; } libspe2-2.2.80-95/tests/helloworld.c0000644000175100017510000000011110600243027016440 0ustar arthurarthur#include main() { printf("Spu says hello!\n"); return 42; } libspe2-2.2.80-95/tests/hellointr.c0000644000175100017510000000037410600243027016300 0ustar arthurarthur#include #include main() { unsigned int data; printf("Spu says hello!\n"); data = 24; spu_write_out_intr_mbox(data); while (spu_stat_out_intr_mbox() == 0) { printf(">> %d\n", spu_stat_out_intr_mbox()); } return 42; } libspe2-2.2.80-95/tests/testlibspe2.c0000644000175100017510000001045010600243027016534 0ustar arthurarthur/* --------------------------------------------------------------- */ /* (C) Copyright 2001,2006, */ /* International Business Machines Corporation, */ /* */ /* All Rights Reserved. */ /* --------------------------------------------------------------- */ /* PROLOG END TAG zYx */ #include #include #include #include int main(void) { spe_context_ptr_t context; int flags = 0; unsigned int entry = SPE_DEFAULT_ENTRY; void *argp = "argp"; void *envp = "envp"; spe_program_handle_t *program; spe_stop_info_t stop_info; int rc; printf("Extering main\n"); printf("Invocation of spe_context_create\n"); if ((context = spe_context_create(flags, NULL)) == NULL) { fprintf(stderr, "Invocation of spe_create_single FAILED, context=%p, errno=%d\n", context, errno); fflush(stderr); return -2; } printf("Invocation of spe_image_open, context=%p\n", context); if ((program = spe_image_open("testlibspe2hello")) == NULL) { fprintf(stderr, "Invocation of spe_image_open FAILED, context=%p, errno=%d\n", context, errno); fflush(stderr); return -1; } printf("Invocation of spe_program_load, context=%p\n", context); if ((rc = spe_program_load(context, program)) != 0) { fprintf(stderr, "Invocation of spe_program_load FAILED, context=%p, rc=%d, errno=%d\n", context, rc, errno); fflush(stderr); return -3; } printf ("Invocation of spe_context_run, content=%p, entry=0x%x, argp=%p, envp=%p\n", context, entry, argp, envp); if ((rc = spe_context_run(context, &entry, 0, argp, envp, &stop_info)) < 0) { fprintf(stderr, "Invocation of spe_context_run FAILED, context=%p, rc=%d, errno=%d\n", context, rc, errno); fflush(stderr); return -4; } printf ("After spe_context_run, context=%p, rc=%d, entry=0x%x, stop_info.stop_reason=0x%x\n", context, rc, entry, stop_info.stop_reason); switch (stop_info.stop_reason) { case SPE_EXIT: printf ("After spe_context_run, context=%p, SPE_EXIT stop_info.result.stop_exit_code=%d\n", context, stop_info.result.spe_exit_code); break; case SPE_STOP_AND_SIGNAL: printf ("After spe_context_run, context=%p, SPE_STOP_AND_SIGNAL stop_info.result.stop_signal_code=%d\n", context, stop_info.result.spe_signal_code); break; case SPE_RUNTIME_ERROR: printf ("After spe_context_run, context=%p, SPE_RUNTIME_ERROR stop_info.result.spe_runtime_error=%d\n", context, stop_info.result.spe_runtime_error); break; case SPE_RUNTIME_EXCEPTION: printf ("After spe_context_run, context=%p, SPE_RUNTIME_EXCEPTION stop_info.result.spe_runtime_exception=%d\n", context, stop_info.result.spe_runtime_exception); break; case SPE_RUNTIME_FATAL: printf ("After spe_context_run, context=%p, SPE_RUNTIME_FATAL stop_info.result.spe_runtime_fatal=%d\n", context, stop_info.result.spe_runtime_fatal); break; case SPE_CALLBACK_ERROR: printf ("After spe_context_run, context=%p, SPE_CALLBACK_ERROR stop_info.result.spe_callback_error=%d\n", context, stop_info.result.spe_callback_error); break; default: printf("After spe_context_run, context=%p, UNKNOWN\n", context); break; } printf ("After spe_context_run, context=%p, stop_info.spu_status=0x%x\n", context, stop_info.spu_status); printf("Invocation of spe_context_destroy, context=%p\n", context); if ((rc = spe_context_destroy(context)) < 0) { fprintf(stderr, "Invocation of spe_context_destroy FAILED, context=%p, rc=%d, errno=%d\n", context, rc, errno); fflush(stderr); return -5; } printf("Exiting main\n"); return 0; } libspe2-2.2.80-95/tests/testevent3.c0000644000175100017510000000244310600243027016403 0ustar arthurarthur/** * Scenario 1: Portable Usage */ #include #define MAX_EVENTS 8 #define SIZE 8 #define COUNT 1 int main() { int i, rc, event_count; spe_event_handler_ptr_t evhandler; spe_event_unit_t event1, event2; //spe_context_ptr_t spe1, spe2; spe_event_unit_t events[MAX_EVENTS]; unsigned int mbox_data[COUNT]; spe_stop_info_t stop_info; /* Create a handle. */ evhandler = spe_event_handler_create(); /* Register events. */ event1.events = SPE_EVENT_OUT_INTR_MBOX | SPE_EVENT_SPE_STOPPED; // rc = spe_epoll_ctl(epfd, SPE_EPOLL_CTL_ADD, spe1, &event1); rc = spe_event_handler_register(evhandler, &event1); event2.events = SPE_EVENT_IN_MBOX | SPE_EVENT_SPE_STOPPED; //rc = spe_epoll_ctl(epfd, SPE_EPOLL_CTL_ADD, spe2, &event2); rc = spe_event_handler_register(evhandler, &event2); /* Get events. */ event_count = spe_event_wait(evhandler, events, MAX_EVENTS, 0); /* Handle events. */ for (i = 0; i < event_count; i++) { if (events[i].events & SPE_EVENT_OUT_INTR_MBOX) { rc = spe_out_intr_mbox_read(events[i].spe, mbox_data, COUNT, SPE_MBOX_ANY_NONBLOCKING); } if (events[i].events & SPE_EVENT_SPE_STOPPED) { rc = spe_stop_info_read(events[i].spe, &stop_info); } } /* Destroy the handle. */ spe_event_handler_destroy(evhandler); return 0; } libspe2-2.2.80-95/tests/testmbox.c0000644000175100017510000000507710602653464016166 0ustar arthurarthur/* --------------------------------------------------------------- */ /* (C) Copyright 2007 */ /* International Business Machines Corporation, */ /* */ /* All Rights Reserved. */ /* --------------------------------------------------------------- */ #include #include #include #include #include "libspe2.h" struct thread_args { struct spe_context * ctx; void * argp; void * envp; }; void * spe_thread(void * arg); __attribute__((noreturn)) void * spe_thread(void * arg) { int flags = 0; unsigned int entry = SPE_DEFAULT_ENTRY; int rc; spe_program_handle_t * program; struct thread_args * arg_ptr; arg_ptr = (struct thread_args *) arg; program = spe_image_open("readmbox"); if (!program) { perror("spe_image_open"); pthread_exit(NULL); } if (spe_program_load(arg_ptr->ctx, program)) { perror("spe_program_load"); pthread_exit(NULL); } rc = spe_context_run(arg_ptr->ctx, &entry, flags, arg_ptr->argp, arg_ptr->envp, NULL); if (rc < 0) perror("spe_context_run"); pthread_exit(NULL); } int main(void) { unsigned int i; unsigned int msgs[8]; struct thread_args t_args; int thread_id; pthread_t pts; spe_context_ptr_t ctx; int rc; ctx = spe_context_create(0, NULL); if (ctx == NULL) { perror("spe_context_create"); return -2; } // check initial status printf("in_mbox:\tspace for %d messages\n", spe_in_mbox_status(ctx)); printf("out_mbox:\tcontains %d messages\n", spe_out_mbox_status(ctx)); printf("out_intr_mbox:\tcontains %d messages\n", spe_out_intr_mbox_status(ctx)); // fill in_mbox one by one for (i=0; i<4; i++) { rc = spe_in_mbox_write(ctx, &i, 1, SPE_MBOX_ALL_BLOCKING); printf("writing %d to in_mbox rc = %d\n", i, rc); printf("in_mbox:\tspace for %d messages\n", spe_in_mbox_status(ctx)); } // try to write one more, but nonblocking rc = spe_in_mbox_write(ctx, &i, 1, SPE_MBOX_ANY_NONBLOCKING); printf("writing %d to in_mbox rc = %d\n", i, rc); t_args.ctx = ctx; // now empty the in_mox from the spe side thread_id = pthread_create( &pts, NULL, &spe_thread, &t_args); // write several messages at once for (i=0; i<8; i++) { msgs[i] = i+1; } rc = spe_in_mbox_write(ctx, msgs, 8, SPE_MBOX_ALL_BLOCKING); printf("writing 8 messages to in_mbox rc = %d\n", rc); printf("in_mbox:\tspace for %d messages\n", spe_in_mbox_status(ctx)); printf("in_mbox:\tspace for %d messages\n", spe_in_mbox_status(ctx)); printf("in_mbox:\tspace for %d messages\n", spe_in_mbox_status(ctx)); pthread_join (pts, NULL); spe_context_destroy(ctx); return 0; } libspe2-2.2.80-95/elfspe/0000755000175100017510000000000010707604274014261 5ustar arthurarthurlibspe2-2.2.80-95/elfspe/elfspe.c0000644000175100017510000001107110625233252015674 0ustar arthurarthur/* * elfspe - A wrapper to allow direct execution of SPE binaries * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define _XOPEN_SOURCE 600 #include #include #include #include #include #include "libspe2.h" #ifndef LS_SIZE #define LS_SIZE 0x40000 /* 256K (in bytes) */ #endif /* LS_SIZE */ static struct spe_context *ctx; static void handler (int signr ) __attribute__ ((noreturn)); static void handler (int signr) { if (ctx) spe_context_destroy(ctx); fprintf (stderr, "Killed by signal %d\n", signr); exit (128 + signr); } struct spe_regs { unsigned int r3[4]; unsigned int r4[4]; unsigned int r5[4]; }; /* spe_copy_argv - setup C99-style argv[] region for SPE main(). * * Duplicate command line arguments and set up argv pointers * to be absolute LS offsets, allowing SPE program to directly * reference these strings from its own LS. * * An SPE entry function (crt0.o) can take the data from spe_regs * and copy the argv region from EA to the top of LS (largest addr), * and set $SP per ABI requirements. Currently, this looks something * like: * * +-----+ 0 * | txt | * |-----| * | | * | ^ | * | | | * | | | * |stack| * |-----| ls_dst (LS_SIZE-nbytes) * | args| * +-----+ LS_SIZE */ static int spe_copy_argv(int argc, char **argv, struct spe_regs *ret) { unsigned int *argv_offsets; void *start = NULL; char *ptr, *end; union { unsigned long long ull; unsigned int ui[2]; } addr64; int spe_arg_max = 4096; int i, nbytes = 0; memset(ret, 0, sizeof(struct spe_regs)); if ((argc <= 0) || getenv("SPE_NO_ARGS")) { return 0; } if (getenv("SPE_ARG_MAX")) { int v; v = strtol((const char *) getenv("SPE_ARG_MAX"), (char **) NULL, 0); if ((v >= 0) && (v <= spe_arg_max)) spe_arg_max = v & ~(15); } for (i = 0; i < argc; i++) { nbytes += strlen(argv[i]) + 1; } nbytes += ((argc + 1) * sizeof(unsigned int)); nbytes = (nbytes + 15) & ~(15); if (nbytes > spe_arg_max) { return 2; } posix_memalign(&start, 16, nbytes); if (!start) { return 3; } addr64.ull = (unsigned long long) ((unsigned long) start); memset(start, 0, nbytes); ptr = (char *)start; end = (char *)start + nbytes; argv_offsets = (unsigned int *) ptr; ptr += ((argc + 1) * sizeof(unsigned int)); for (i = 0; i < argc; i++) { int len = strlen(argv[i]) + 1; argv_offsets[i] = LS_SIZE - ((unsigned int) (end - ptr)); argv_offsets[i] &= LS_SIZE-1; memcpy(ptr, argv[i], len); ptr += len; } argv_offsets[argc] = NULL; ret->r3[0] = argc; ret->r4[0] = LS_SIZE - nbytes; ret->r4[1] = addr64.ui[0]; ret->r4[2] = addr64.ui[1]; ret->r4[3] = nbytes; return 0; } int main (int argc, char **argv) { int flags = 0; unsigned int entry = SPE_DEFAULT_ENTRY; struct spe_regs params; int rc; spe_stop_info_t stop_info; spe_program_handle_t *spe_handle; signal (SIGSEGV, handler); signal (SIGBUS, handler); signal (SIGILL, handler); signal (SIGFPE, handler); signal (SIGTERM, handler); signal (SIGHUP, handler); signal (SIGINT, handler); if (argc < 2) { fprintf (stderr, "Usage: elfspe [spe-elf]\n"); exit (1); } spe_handle = spe_image_open (argv[1]); if (!spe_handle) { perror (argv[1]); exit (1); } if (spe_copy_argv(argc-1, &argv[1], ¶ms)) { perror ("spe_copy_argv"); exit (1); } ctx = spe_context_create(flags, NULL); if (ctx == NULL) { perror("spe_create_single"); exit(1); } if (spe_program_load(ctx, spe_handle)) { perror("spe_load"); exit(1); } rc = spe_context_run(ctx, &entry, SPE_RUN_USER_REGS, ¶ms, NULL, &stop_info); if (rc < 0) perror("spe_run"); spe_context_destroy(ctx); return stop_info.result.spe_exit_code; } libspe2-2.2.80-95/elfspe/scripts/0000755000175100017510000000000010707604274015750 5ustar arthurarthurlibspe2-2.2.80-95/elfspe/scripts/elfspe-register0000644000175100017510000000036510600243027020762 0ustar arthurarthur#!/bin/sh if test -f /proc/sys/fs/binfmt_misc/spe then echo "elfspe already registered" else echo ':spe:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x17::@BINDIR@/elfspe:' \ >/proc/sys/fs/binfmt_misc/register fi libspe2-2.2.80-95/elfspe/scripts/elfspe-unregister0000644000175100017510000000006110600243027021316 0ustar arthurarthur#!/bin/sh echo -1 > /proc/sys/fs/binfmt_misc/spe libspe2-2.2.80-95/elfspe/Makefile0000644000175100017510000000321510600243027015705 0ustar arthurarthur#* #* libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS #* Copyright (C) 2005 IBM Corp. #* #* This library is free software; you can redistribute it and/or modify it #* under the terms of the GNU Lesser General Public License as published by #* the Free Software Foundation; either version 2.1 of the License, #* or (at your option) any later version. #* #* This library is distributed in the hope that it will be useful, but #* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY #* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public #* License for more details. #* #* You should have received a copy of the GNU Lesser General Public License #* along with this library; if not, write to the Free Software Foundation, #* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #* TOP=.. include $(TOP)/make.defines CFLAGS += -I$(TOP) CFLAGS += -I$(TOP)/spebase LDFLAGS := $(CFLAGS) LDLIBS := -L$(TOP) -lspe2 elfspe_OBJS := elfspe.o all: elfspe elfspe: $(elfspe_OBJS) $(CC) $(CFLAGS) -o $@ $< $(TOP)/$(libspe2_SO) clean: rm -f $(elfspe_OBJS) elfspe install: elfspe elfspe-register $(INSTALL_DIR) $(ROOT)$(bindir) $(INSTALL_PROGRAM) elfspe $(ROOT)$(bindir)/elfspe $(INSTALL_PROGRAM) elfspe-register $(ROOT)$(bindir)/elfspe-register $(INSTALL_PROGRAM) scripts/elfspe-unregister $(ROOT)$(bindir)/elfspe-unregister # # when building in the cross environment this script should reference the # boot-time relative location not the sysroot relative location. # elfspe-register: scripts/elfspe-register sed -e "s%@BINDIR@%${bindir}%g" <$< >$@ chmod +x $@ libspe2-2.2.80-95/doc/0000755000175100017510000000000010707604274013550 5ustar arthurarthurlibspe2-2.2.80-95/doc/img/0000755000175100017510000000000010707604274014324 5ustar arthurarthurlibspe2-2.2.80-95/doc/img/Makefile0000644000175100017510000000022510600243027015746 0ustar arthurarthur images = singlemini.pdf pthreadmini.pdf event1.pdf all: $(images) $(images): %.pdf: %.dot dot -Tps $< | epstopdf -f -o $@ clean: rm $(images)libspe2-2.2.80-95/doc/img/singlemini.dot0000644000175100017510000000134710600243027017162 0ustar arthurarthurdigraph G { subgraph cluster_0 { style=filled; color=lightgrey; node [style=filled,color=white]; spe_image_open -> spe_context_create -> spe_program_load -> spe_context_run -> spe_context_destroy label = "ppe program"; } subgraph cluster_1 { node [style=filled]; hello; label = "spe program"; color=black } ; start -> spe_image_open; spe_context_run -> hello [tailport = ne headport = n ]; hello -> spe_context_run [tailport = w headport = se ]; spe_context_destroy -> end; start [shape=Mdiamond]; end [shape=Msquare]; } libspe2-2.2.80-95/doc/img/event1.dot0000644000175100017510000000204510600243027016222 0ustar arthurarthurdigraph G { subgraph cluster_0 { style=filled; color=lightgrey; node [style=filled,color=white]; spe_context_create -> spe_image_open -> spe_program_load -> spe_event_handler_create -> spe_event_handler_register -> spe_context_run -> spe_event_wait -> spe_stop_info_read -> spe_event_handler_destroy -> spe_context_destroy label = "ppe program"; } subgraph cluster_1 { node [style=filled]; hello; label = "spe program"; color=black } node [shape=box,style=filled] event; start -> spe_context_create; spe_context_run -> hello [tailport = ne headport = n]; hello -> spe_context_run [tailport = w headport = se ]; hello -> event [tailport = s headport = n label="SPE_EVENT_SPE_STOPPED"]; spe_event_wait -> event [tailport = e headport = w]; spe_context_destroy -> end; start [shape=Mdiamond]; end [shape=Msquare]; } libspe2-2.2.80-95/doc/img/pthreadmini.dot0000644000175100017510000000211510600243027017322 0ustar arthurarthurdigraph G { subgraph cluster_0 { style=filled; color=lightgrey; node [style=filled,color=white]; spe_context_create -> pthread_create -> pthread_join -> spe_context_destroy; label = "ppe program"; } subgraph cluster_1 { style=filled; color=lightgrey; node [style=filled,color=white]; spe_image_open -> spe_program_load -> spe_context_run -> pthread_exit; label = "spethread"; } subgraph cluster_2 { node [style=filled]; hello; label = "spe program"; color=black } ; start -> spe_context_create; pthread_create -> spe_image_open; spe_context_run -> hello [tailport = ne headport = n ]; hello -> spe_context_run [tailport = w headport = se ]; pthread_exit -> pthread_join [tailport = w headport = e]; spe_context_destroy -> end; start [shape=Mdiamond]; end [shape=Msquare]; } libspe2-2.2.80-95/doc/LatexHeader0000644000175100017510000000542510600243027015652 0ustar arthurarthur\documentclass[a4paper]{book} \usepackage{a4wide} \usepackage{makeidx} \usepackage{fancyhdr} \usepackage{graphicx} \usepackage{multicol} \usepackage{float} \usepackage{textcomp} \usepackage{alltt} \usepackage{times} \ifx\pdfoutput\undefined \usepackage[ps2pdf, pagebackref=true, colorlinks=true, linkcolor=blue ]{hyperref} \usepackage{pspicture} \else \usepackage[pdftex, pagebackref=true, colorlinks=true, linkcolor=blue ]{hyperref} \fi \usepackage{../doc/doxygen} \makeindex \setcounter{tocdepth}{1} \renewcommand{\footrulewidth}{0.4pt} \begin{document} \begin{titlepage} \begin{flushleft} \vspace*{2cm} \rule{15cm}{1mm} \huge SPE Runtime Management Library \end{flushleft} \begin{flushleft} \vspace*{4cm} \rule{15cm}{1mm} \LARGE Version 2.0 \end{flushleft} \begin{flushright} \vspace*{4cm} \end{flushright} \begin{flushleft} \vspace*{5cm} \today \end{flushleft} \end{titlepage} \vspace*{2cm} \copyright Copyright International Business Machines Corporation, Sony Computer Entertainment Incorporated, Toshiba Corporation 2003, 2004, 2005, 2006\\ \\ All Rights Reserved\\ Printed in the United States of America June 2006\\ \\ The following are trademarks of International Business Machines Corporation in the United States, or other countries, or both.\\ \\ IBM PowerPC\\ IBM Logo PowerPC Architecture\\ \\ Other company, product, and service names may be trademarks or service marks of others. All information contained in this document is subject to change without notice. The products described in this document are NOT intended for use in applications such as implantation, life support, or other hazardous uses where malfunction could result in death, bodily injury, or catastrophic property damage. The information contained in this document does not affect or change IBM product specifications or warranties. Nothing in this document shall operate as an express or implied license or indemnity under the intellectual property rights of IBM or third parties. All information contained in this document was obtained in specific environments, and is presented as an illustration. The results obtained in other operating environments may vary.\\ \\ THE INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED ON AN ``AS IS'' BASIS. In no event will IBM be liable for damages arising directly or indirectly from any use of the information contained in this document.\\ \\ IBM Systems and Technology Group\\ 2070 Route 52, Bldg. 330\\ Hopewell Junction, NY 12533-6351\\ \\ The IBM home page can be found at ibm.com\\ \\ The IBM semiconductor solutions home page can be found at ibm.com/chips\\ \\ June 15, 2006 \clearemptydoublepage \pagenumbering{roman} \tableofcontents \clearemptydoublepage \pagenumbering{arabic} libspe2-2.2.80-95/doc/design.txt0000644000175100017510000000732010600243027015547 0ustar arthurarthur/** \mainpage Overview The libspe2 functionality is split into 4 libraries: - libspe-base This library provides the basic infrastructure to manage and use SPEs. The central data structure is a SPE context spe_context. It contains all information necessary to manage an SPE, run code on it, communicate with it, and so on. To use the libspe-base library, the header file spebase.h has to be included and and an application needs to link against libspebase.a or libspebase.so. - libspe-event This is a convenience library for the handling of events generated by an SPE. It is based on libspe-base and epoll. Since the spe_context introduced by libspe-base contains the file descriptors to mailboxes etc, any other event handling mechanism could also be implemented based on libspe-base. \section Terminology - main thread usually the application main thread running on a PPE - SPE thread a thread that uses SPEs. Execution starts on the PPE. Execution shifts between PPE and an SPE back and fro, e.g., PPE services system calls for SPE transparently \section use-case Usage Scenarios \subsection single Single-threaded sample Note: In the new model, it is not necessary to have a main thread - the SPE thread can be the only application thread. It may run parts of its code on PPE and then start an SPE, e.g., for an accelerated function. The main thread is needed only if you want to use multiple SPEs concurrently. The following minimalistic sample illustrates the basic steps: \image latex singlemini.eps "Simple program" width=6cm \include testsinglemini.c Here is the same sample with some error checking: \include testsingle.c \subsection multi Multi-threaded sample This illustrates a threaded sample using the pthread library: \image latex pthreadmini.eps "Simple pthread program" width=6cm \include testpthreadmini.c Here is the same sample with some error checking: \include testpthread.c \subsection problem Problem state mapping samples This illustrates accessing the MFC Local Store Address Register. \include testmap1.c \subsection event Event samples This illustrates a sample using the event libary. The event, which we receive is of course that the spu program has stopped, because otherwise we would not get there. \image latex event1.eps "Simple event program" width=6cm \include testevent1.c Events are more useful in multithreaded environments: \include testevent2.c */ /* This illustrates a sample using the event libary. \include testevent4.c - libspe-gang This is a convenience library for SPE gangs. It uses libspe-base and pthreads to set up and run gangs of SPE threads. The main thread "sees" a single pthread for the whole gang of N plus N SPE contexts. As with libspe-thread, we need the SPE contexts explicitly to be able to use libspe-base. - libspe-thread This is a convenience library that provides a pthread-based implementation of a thread model similar to libspe 1.1. In order to be able to use libspe-base functions, we need the SPE context associated with the pthread NB: In this version of the document, we concentrate on the libspe base part and eliminated all other parts temporarily. \subsection gang Multi-threaded gang samples This illustrates a threaded gang sample where the main thread starts all the spe threads: \include testgang1.c This illustrates a threaded gang sample with a gang master thread. The main thread only starts the gang thread, which in turn starts all the spe threads: \include testgang2.c \subsection thread Spethread samples This illustrates a sample using the thread convenience libary. \include testspethread.c */ /* \image html cbea.png \image latex cbea.png */libspe2-2.2.80-95/doc/DoxyfileRef0000644000175100017510000013524610600243027015711 0ustar arthurarthur# Doxyfile 1.3.9.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = libspe2 # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = 0.9a # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of source # files, where putting all generated files in the same directory would otherwise # cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, # Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, # Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, # Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, # Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # This tag can be used to specify the encoding used in the generated output. # The encoding is not always determined by the language that is chosen, # but also whether or not the output is meant for Windows or non-Windows users. # In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES # forces the Windows encoding (this is the default for the Windows binary), # whereas setting the tag to NO uses a Unix-style encoding (the default for # all platforms other than Windows). USE_WINDOWS_ENCODING = NO # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = NO # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is used # as the annotated text. Otherwise, the brief description is used as-is. If left # blank, the following values are used ("$name" is automatically replaced with the # name of the entity): "The $name class" "The $name widget" "The $name file" # "is" "provides" "specifies" "contains" "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited # members of a class in the documentation of that class as if those members were # ordinary class members. Constructors, destructors and assignment operators of # the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like the Qt-style comments (thus requiring an # explicit @brief command for a brief description. JAVADOC_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. # If set to NO, the detailed description appears after the member # documentation. DETAILS_AT_TOP = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources # only. Doxygen will then generate output that is more tailored for Java. # For instance, namespaces will be presented as packages, qualified scopes # will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = NO # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = YES # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = YES # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = YES # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = YES # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = NO # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = NO # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. SHOW_DIRECTORIES = NO #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = doc/design.txt libspe2.h libspe2-types.h #INPUT = doc/design.txt spebase speevent spethread spegang # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp # *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories # that are symbolic links (a Unix filesystem feature) are excluded from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. EXCLUDE_PATTERNS = default* # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = $(PWD)/tests # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = $(HOME) # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = NO #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = NO # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = YES # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = doc/LatexHeader # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = YES #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = YES # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_PREDEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse the # parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or # super classes. Setting the tag to NO turns the diagrams off. Note that this # option is superseded by the HAVE_DOT option below. This is only a fallback. It is # recommended to install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = YES # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will # generate a call dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected # functions only using the \callgraph command. CALL_GRAPH = YES # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found on the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_WIDTH = 1024 # The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_HEIGHT = 1024 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes that # lay further from the root node will be omitted. Note that setting this option to # 1 or 2 may greatly reduce the computation time needed for large code bases. Also # note that a graph may be further truncated if the graph's image dimensions are # not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). # If 0 is used for the depth value (the default), the graph is not depth-constrained. MAX_DOT_GRAPH_DEPTH = 0 # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO libspe2-2.2.80-95/doc/doxygen.sty0000644000175100017510000000436710600243027015763 0ustar arthurarthur\NeedsTeXFormat{LaTeX2e} \ProvidesPackage{doxygen} \RequirePackage{calc} \RequirePackage{array} \pagestyle{fancyplain} \newcommand{\clearemptydoublepage}{\newpage{\pagestyle{empty}\cleardoublepage}} \renewcommand{\chaptermark}[1]{\markboth{#1}{}} \renewcommand{\sectionmark}[1]{\markright{\thesection\ #1}} \lhead[\fancyplain{}{\bfseries\thepage}] {\fancyplain{}{\bfseries\rightmark}} \rhead[\fancyplain{}{\bfseries\leftmark}] {\fancyplain{}{\bfseries\thepage}} \rfoot[\fancyplain{}{\bfseries\scriptsize SPE Runtime Management Library, Version 2.0 }]{} \lfoot[]{\fancyplain{}{\bfseries\scriptsize SPE Runtime Management Library, Version 2.0 }} \cfoot{} \newenvironment{Code} {\footnotesize} {\normalsize} \newcommand{\doxyref}[3]{\textbf{#1} (\textnormal{#2}\,\pageref{#3})} \newenvironment{DocInclude} {\footnotesize} {\normalsize} \newenvironment{VerbInclude} {\footnotesize} {\normalsize} \newenvironment{Image} {\begin{figure}[H]} {\end{figure}} \newenvironment{ImageNoCaption}{}{} \newenvironment{CompactList} {\begin{list}{}{ \setlength{\leftmargin}{0.5cm} \setlength{\itemsep}{0pt} \setlength{\parsep}{0pt} \setlength{\topsep}{0pt} \renewcommand{\makelabel}{}}} {\end{list}} \newenvironment{CompactItemize} { \begin{itemize} \setlength{\itemsep}{-3pt} \setlength{\parsep}{0pt} \setlength{\topsep}{0pt} \setlength{\partopsep}{0pt} } {\end{itemize}} \newcommand{\PBS}[1]{\let\temp=\\#1\let\\=\temp} \newlength{\tmplength} \newenvironment{TabularC}[1] { \setlength{\tmplength} {\linewidth/(#1)-\tabcolsep*2-\arrayrulewidth*(#1+1)/(#1)} \par\begin{tabular*}{\linewidth} {*{#1}{|>{\PBS\raggedright\hspace{0pt}}p{\the\tmplength}}|} } {\end{tabular*}\par} \newcommand{\entrylabel}[1]{ {\parbox[b]{\labelwidth-4pt}{\makebox[0pt][l]{\textbf{#1}}\\}}} \newenvironment{Desc} {\begin{list}{} { \settowidth{\labelwidth}{40pt} \setlength{\leftmargin}{\labelwidth} \setlength{\parsep}{0pt} \setlength{\itemsep}{-4pt} \renewcommand{\makelabel}{\entrylabel} } } {\end{list}} \newenvironment{Indent} {\begin{list}{}{\setlength{\leftmargin}{0.5cm}} \item[]\ignorespaces} {\unskip\end{list}} \setlength{\parindent}{0cm} \setlength{\parskip}{0.2cm} \addtocounter{secnumdepth}{1} \sloppy \usepackage[T1]{fontenc} libspe2-2.2.80-95/doc/ARCHITECTURE0000644000175100017510000000102110600243027015332 0ustar arthurarthurspe_create() ------------ Creates a new SPE context, allocates structures, maps SPE memory areas, and opens needes spufs files. spe_load() ---------- Loads an SPE-ELF binary opened with spe_open_image() or an embedded SPE object and transfers it to the SPE. spe_exec() ---------- Starts execution on the SPE. Returns when the SPE has run to an end, or if an unrecoverable error has occurred. spe_open_image() (OLD) ---------------------- Opens a SPE object file so it can be read, loaded, and transferred to the SPE. libspe2-2.2.80-95/doc/extractfunctions.xslt0000644000175100017510000000134310600243027020053 0ustar arthurarthur ; libspe2-2.2.80-95/doc/Doxyfile0000644000175100017510000013532710600243027015254 0ustar arthurarthur# Doxyfile 1.3.9.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = libspe2 # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = 0.9a # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of source # files, where putting all generated files in the same directory would otherwise # cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, # Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, # Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, # Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, # Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # This tag can be used to specify the encoding used in the generated output. # The encoding is not always determined by the language that is chosen, # but also whether or not the output is meant for Windows or non-Windows users. # In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES # forces the Windows encoding (this is the default for the Windows binary), # whereas setting the tag to NO uses a Unix-style encoding (the default for # all platforms other than Windows). USE_WINDOWS_ENCODING = NO # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is used # as the annotated text. Otherwise, the brief description is used as-is. If left # blank, the following values are used ("$name" is automatically replaced with the # name of the entity): "The $name class" "The $name widget" "The $name file" # "is" "provides" "specifies" "contains" "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited # members of a class in the documentation of that class as if those members were # ordinary class members. Constructors, destructors and assignment operators of # the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like the Qt-style comments (thus requiring an # explicit @brief command for a brief description. JAVADOC_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. # If set to NO, the detailed description appears after the member # documentation. DETAILS_AT_TOP = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources # only. Doxygen will then generate output that is more tailored for Java. # For instance, namespaces will be presented as packages, qualified scopes # will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = YES # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = YES # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. SHOW_DIRECTORIES = NO #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = doc/design.txt libspe2.h libspe2-types.h spebase speevent #INPUT = doc/design.txt spebase speevent spethread spegang # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp # *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories # that are symbolic links (a Unix filesystem feature) are excluded from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. EXCLUDE_PATTERNS = default* # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = $(HOME)/workspace/head-libspe2/tests # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = $(HOME) # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = YES # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = YES # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = doc/LatexHeader # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = YES #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_PREDEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse the # parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or # super classes. Setting the tag to NO turns the diagrams off. Note that this # option is superseded by the HAVE_DOT option below. This is only a fallback. It is # recommended to install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = YES # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = YES # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will # generate a call dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected # functions only using the \callgraph command. CALL_GRAPH = YES # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found on the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_WIDTH = 1024 # The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_HEIGHT = 1024 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes that # lay further from the root node will be omitted. Note that setting this option to # 1 or 2 may greatly reduce the computation time needed for large code bases. Also # note that a graph may be further truncated if the graph's image dimensions are # not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). # If 0 is used for the depth value (the default), the graph is not depth-constrained. MAX_DOT_GRAPH_DEPTH = 0 # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO libspe2-2.2.80-95/libspe2-types.h0000644000175100017510000001635110704604241015653 0ustar arthurarthur/* * libspe2 - A wrapper to allow direct execution of SPE binaries * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef libspe2_types_h #define libspe2_types_h #ifdef __cplusplus extern "C" { #endif #include #include "cbea_map.h" /* * Data structure declarations for * SPE problem state areas * (part of public API) */ /** SPE program handle * Structure spe_program_handle per CESOF specification * libspe2 applications usually only keep a pointer * to the program handle and do not use the structure * directly. */ typedef struct spe_program_handle { /* * handle_size allows for future extensions of the spe_program_handle * struct by new fields, without breaking compatibility with existing users. * Users of the new field would check whether the size is large enough. */ unsigned int handle_size; void *elf_image; void *toe_shadow; } spe_program_handle_t; /** SPE context * The SPE context is one of the base data structures for * the libspe2 implementation. It holds all persistent information * about a "logical SPE" used by the application. This data * structure should not be accessed directly, but the application * uses a pointer to an SPE context as an identifier for the * "logical SPE" it is dealing with through libspe2 API calls. */ struct spe_context { /* * Note: The debugger accesses this data structure, and assumes * it starts out with an spe_program_handle_t identifying the SPE * executable running within this SPE thread. Everything below * is private to libspe. */ spe_program_handle_t handle; /* * PRIVATE TO IMPLEMENTATION - DO NOT USE DIRECTLY */ struct spe_context_base_priv * base_private; struct spe_context_event_priv * event_private; }; /** spe_context_ptr_t * This pointer serves as the identifier for a specific * SPE context throughout the API (where needed) */ typedef struct spe_context * spe_context_ptr_t; /** SPE gang context * The SPE gang context is one of the base data structures for * the libspe2 implementation. It holds all persistent information * about a group of SPE contexts that should be treated as a gang, * i.e., be execute together with certain properties. This data * structure should not be accessed directly, but the application * uses a pointer to an SPE gang context as an identifier for the * SPE gang it is dealing with through libspe2 API calls. */ struct spe_gang_context { /* * PRIVATE TO IMPLEMENTATION - DO NOT USE DIRECTLY */ struct spe_gang_context_base_priv * base_private; struct spe_gang_context_event_priv * event_private; }; /** spe_gang_context_ptr_t * This pointer serves as the identifier for a specific * SPE gang context throughout the API (where needed) */ typedef struct spe_gang_context * spe_gang_context_ptr_t; /* * SPE stop information * This structure is used to return all information available * on the reason why an SPE program stopped execution. * This information is important for some advanced programming * patterns and/or detailed error reporting. */ /** spe_stop_info_t */ typedef struct spe_stop_info { unsigned int stop_reason; union { int spe_exit_code; int spe_signal_code; int spe_runtime_error; int spe_runtime_exception; int spe_runtime_fatal; int spe_callback_error; int spe_isolation_error; /* Reserved fields */ void *__reserved_ptr; unsigned long long __reserved_u64; } result; int spu_status; } spe_stop_info_t; /* * SPE event structure * This structure is used for SPE event handling */ /** spe_event_data_t * User data to be associated with an event */ typedef union spe_event_data { void *ptr; unsigned int u32; unsigned long long u64; } spe_event_data_t; /** spe_event_t */ typedef struct spe_event_unit { unsigned int events; spe_context_ptr_t spe; spe_event_data_t data; } spe_event_unit_t; typedef void* spe_event_handler_ptr_t; typedef int spe_event_handler_t; /* *--------------------------------------------------------- * * API symbolic constants * *--------------------------------------------------------- */ enum ps_area { SPE_MSSYNC_AREA, SPE_MFC_COMMAND_AREA, SPE_CONTROL_AREA, SPE_SIG_NOTIFY_1_AREA, SPE_SIG_NOTIFY_2_AREA }; /** * Flags for spe_context_create */ #define SPE_CFG_SIGNOTIFY1_OR 0x00000010 #define SPE_CFG_SIGNOTIFY2_OR 0x00000020 #define SPE_MAP_PS 0x00000040 #define SPE_ISOLATE 0x00000080 #define SPE_ISOLATE_EMULATE 0x00000100 #define SPE_EVENTS_ENABLE 0x00001000 #define SPE_AFFINITY_MEMORY 0x00002000 /** * Symbolic constants for stop reasons * as returned in spe_stop_info_t */ #define SPE_EXIT 1 #define SPE_STOP_AND_SIGNAL 2 #define SPE_RUNTIME_ERROR 3 #define SPE_RUNTIME_EXCEPTION 4 #define SPE_RUNTIME_FATAL 5 #define SPE_CALLBACK_ERROR 6 #define SPE_ISOLATION_ERROR 7 /** * Runtime errors */ #define SPE_SPU_STOPPED_BY_STOP 0x02 /* INTERNAL USE ONLY */ #define SPE_SPU_HALT 0x04 #define SPE_SPU_WAITING_ON_CHANNEL 0x08 /* INTERNAL USE ONLY */ #define SPE_SPU_SINGLE_STEP 0x10 #define SPE_SPU_INVALID_INSTR 0x20 #define SPE_SPU_INVALID_CHANNEL 0x40 /** * Runtime exceptions */ #define SPE_DMA_ALIGNMENT 0x0008 /* #define SPE_SPE_ERROR 0x0010 */ #define SPE_DMA_SEGMENTATION 0x0020 #define SPE_DMA_STORAGE 0x0040 #define SPE_INVALID_DMA 0x0800 /** * SIGSPE maps to SIGURG */ #define SIGSPE SIGURG /** * Supported SPE events */ #define SPE_EVENT_OUT_INTR_MBOX 0x00000001 #define SPE_EVENT_IN_MBOX 0x00000002 #define SPE_EVENT_TAG_GROUP 0x00000004 #define SPE_EVENT_SPE_STOPPED 0x00000008 #define SPE_EVENT_ALL_EVENTS SPE_EVENT_OUT_INTR_MBOX | \ SPE_EVENT_IN_MBOX | \ SPE_EVENT_TAG_GROUP | \ SPE_EVENT_SPE_STOPPED /** * Behavior flags for mailbox read/write functions */ #define SPE_MBOX_ALL_BLOCKING 1 #define SPE_MBOX_ANY_BLOCKING 2 #define SPE_MBOX_ANY_NONBLOCKING 3 /** * Behavior flags tag status functions */ #define SPE_TAG_ALL 1 #define SPE_TAG_ANY 2 #define SPE_TAG_IMMEDIATE 3 /** * Flags for _base_spe_context_run */ #define SPE_DEFAULT_ENTRY UINT_MAX #define SPE_RUN_USER_REGS 0x00000001 /* 128b user data for r3-5. */ #define SPE_NO_CALLBACKS 0x00000002 /* * */ #define SPE_CALLBACK_NEW 1 #define SPE_CALLBACK_UPDATE 2 #define SPE_COUNT_PHYSICAL_CPU_NODES 1 #define SPE_COUNT_PHYSICAL_SPES 2 #define SPE_COUNT_USABLE_SPES 3 /** * Signal Targets */ #define SPE_SIG_NOTIFY_REG_1 0x0001 #define SPE_SIG_NOTIFY_REG_2 0x0002 #ifdef __cplusplus } #endif #endif /*libspe2_types_h*/ libspe2-2.2.80-95/spebase/0000755000175100017510000000000010707604273014424 5ustar arthurarthurlibspe2-2.2.80-95/spebase/dma.h0000644000175100017510000000254510600243027015330 0ustar arthurarthur/* * libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _dma_h_ #define _dma_h_ #include #include "spebase.h" struct mfc_command_parameter_area { uint32_t pad; /* reserved */ uint32_t lsa; /* local storage address */ uint64_t ea; /* effective address */ uint16_t size; /* transfer size */ uint16_t tag; /* command tag */ uint16_t class; /* class ID */ uint16_t cmd; /* command opcode */ }; enum mfc_cmd { MFC_CMD_PUT = 0x20, MFC_CMD_PUTB = 0x21, MFC_CMD_PUTF = 0x22, MFC_CMD_GET = 0x40, MFC_CMD_GETB = 0x41, MFC_CMD_GETF = 0x42, }; #endif libspe2-2.2.80-95/spebase/default_posix1_handler.c0000644000175100017510000016152310650126261021215 0ustar arthurarthur/* default_posix1_handler.c - emulate SPE POSIX.1 library calls. * * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "default_posix1_handler.h" #include "handler_utils.h" /* SPE POSIX.1 Handlers - Overview: * This file implements handlers for SPE POSIX.1 library calls such as * open(2), using C library facilities available on PPE. * * The main contribution of this layer is to provide the SPE programer * with a set of utilities that operate on a large effective address * space, rather than LS objects. For instance this feature can be * used to to mmap(2) a data file into an address space and then * multi-buffer data into LS in order to avoid staging via expensive * buffered-I/O calls (e.g. fread(3)). * * SPE-side: * The SPE-side of this interface is implemented with a set of small stub * routines, which may be packaged into an SPE POSIX.1-compatible library. * These stubs are responsible for pushing SPE register parameters onto the * stack, and then executing a stop-and-signal instruction with a reserved * signal code (currently 0x2101). By convention, the next word following * the stop-and-signal instruction will contain the POSIX.1 op-code along * with a pointer to the beginning of the call stack frame. * * PPE-side: * The PPE application or library receives stop-and-signal notification * from the OS. The default_posix1_handler() routine is then called in order * to parse the POSIX.1 op-code and branch to a specific POSIX.1 handler, * such as default_posix1_handler_open(). * * The POSIX.1 handlers use direct-mapped access to LS in order to fetch * parameters from the stack frame, and to place return values (including * errno) into the expected locations. * * Errata: * This code is (hopefully) just temporary, until built-in OS support for * SPE syscalls is implemented. * * Enable SPE_POSIX1_SHM_CALLS if the various shm_ operations are needed * by the SPE. This requires applications link with -lrt, so it is * currently disabled by default, and will return ENOSYS back to the * SPE. */ #define SPE_POSIX1_OP_SHIFT 24 #define SPE_POSIX1_OP_MASK 0xff #define SPE_POSIX1_DATA_MASK 0xffffff #define SPE_POSIX1_OP(_v) (((_v) >> SPE_POSIX1_OP_SHIFT) & SPE_POSIX1_OP_MASK) #define SPE_POSIX1_DATA(_v) ((_v) & SPE_POSIX1_DATA_MASK) enum { SPE_POSIX1_UNUSED, SPE_POSIX1_ADJTIMEX, SPE_POSIX1_CLOSE, SPE_POSIX1_CREAT, SPE_POSIX1_FSTAT, SPE_POSIX1_FTOK , SPE_POSIX1_GETPAGESIZE, SPE_POSIX1_GETTIMEOFDAY, SPE_POSIX1_KILL, SPE_POSIX1_LSEEK, SPE_POSIX1_LSTAT, SPE_POSIX1_MMAP, SPE_POSIX1_MREMAP, SPE_POSIX1_MSYNC, SPE_POSIX1_MUNMAP, SPE_POSIX1_OPEN, SPE_POSIX1_READ, SPE_POSIX1_SHMAT, SPE_POSIX1_SHMCTL, SPE_POSIX1_SHMDT, SPE_POSIX1_SHMGET, SPE_POSIX1_SHM_OPEN, SPE_POSIX1_SHM_UNLINK, SPE_POSIX1_STAT, SPE_POSIX1_UNLINK, SPE_POSIX1_WAIT, SPE_POSIX1_WAITPID, SPE_POSIX1_WRITE, /* added to support fortran frontend */ SPE_POSIX1_FTRUNCATE, SPE_POSIX1_ACCESS, SPE_POSIX1_DUP, SPE_POSIX1_TIME, SPE_POSIX1_NANOSLEEP, SPE_POSIX1_CHDIR, SPE_POSIX1_FCHDIR, SPE_POSIX1_MKDIR, SPE_POSIX1_MKNOD, SPE_POSIX1_RMDIR, SPE_POSIX1_CHMOD, SPE_POSIX1_FCHMOD, SPE_POSIX1_CHOWN, SPE_POSIX1_FCHOWN, SPE_POSIX1_LCHOWN, SPE_POSIX1_GETCWD, SPE_POSIX1_LINK, SPE_POSIX1_SYMLINK, SPE_POSIX1_READLINK, SPE_POSIX1_SYNC, SPE_POSIX1_FSYNC, SPE_POSIX1_FDATASYNC, SPE_POSIX1_DUP2, SPE_POSIX1_LOCKF, SPE_POSIX1_TRUNCATE, SPE_POSIX1_MKSTEMP, SPE_POSIX1_MKTEMP, SPE_POSIX1_OPENDIR, SPE_POSIX1_CLOSEDIR, SPE_POSIX1_READDIR, SPE_POSIX1_REWINDDIR, SPE_POSIX1_SEEKDIR, SPE_POSIX1_TELLDIR, SPE_POSIX1_SCHED_YIELD, SPE_POSIX1_UMASK, SPE_POSIX1_UTIME, SPE_POSIX1_UTIMES, SPE_POSIX1_PREAD, SPE_POSIX1_PWRITE, SPE_POSIX1_READV, SPE_POSIX1_WRITEV, SPE_POSIX1_LAST_OPCODE, }; #define SPE_POSIX1_NR_OPCODES \ ((SPE_POSIX1_LAST_OPCODE - SPE_POSIX1_ADJTIMEX) + 1) typedef union { unsigned long long all64; unsigned int by32[2]; } addr64; /* SPE-compatable stat structure. */ struct spe_compat_stat { unsigned int dev; unsigned int ino; unsigned int mode; unsigned int nlink; unsigned int uid; unsigned int gid; unsigned int rdev; unsigned int size; unsigned int blksize; unsigned int blocks; unsigned int atime; unsigned int mtime; unsigned int ctime; }; /* SPE-compatable timeval structure. */ struct spe_compat_timeval { int tv_sec; int tv_usec; }; /* SPE-compatable timezone structure. */ struct spe_compat_timezone { int tz_minuteswest; int tz_dsttime; }; struct spe_compat_timespec { int tv_sec; int tv_nsec; }; struct spe_compat_utimbuf { int actime; int modtime; }; /* SPE-compatable timex structure. */ struct spe_compat_timex { unsigned int modes; int offset; int freq; int maxerror; int esterror; int status; int constant; int precision; int tolerance; struct spe_compat_timeval time; int tick; int ppsfreq; int jitter; int shift; int stabil; int jitcnt; int calcnt; int errcnt; int stbcnt; int :32; int :32; int :32; int :32; int :32; int :32; int :32; int :32; int :32; int :32; int :32; int :32; }; struct spe_compat_dirent { uint32_t d_ino; char d_name[256]; }; static inline void *spe_reg128toptr(struct spe_reg128 *reg) { addr64 a64; a64.by32[0] = reg->slot[0]; a64.by32[1] = reg->slot[1]; return (void *) (unsigned long) a64.all64; } static inline uint64_t spe_ptrto64 (void *ptr) { return (uint64_t) (unsigned long) ptr; } static void spe_copy_dirent(struct spe_compat_dirent *spe_ent, struct dirent *ent) { spe_ent->d_ino = ent->d_ino; memcpy(spe_ent->d_name, ent->d_name, sizeof(spe_ent->d_name)); } /* * Needs to be compiled with -D_XOPEN_SOURCE to get IOV_MAX, but that * sounds bad: IOV_MAX is the maximum number of vectors for readv and * writev calls. */ #ifndef IOV_MAX #define IOV_MAX 1024 #endif #define SPU_SSIZE_MAX 0x7fffffffL struct ls_iovec { uint32_t iov_base; uint32_t iov_len; }; static int check_conv_spuvec(char *ls, struct iovec *vec, struct ls_iovec *lsvec, int count) { int i; size_t sum; if (count > IOV_MAX) { errno = EINVAL; return -1; } sum = 0; for (i = 0; i < count; i++) { vec[i].iov_base = GET_LS_PTR(lsvec[i].iov_base); vec[i].iov_len = lsvec[i].iov_len; if (sum + vec[i].iov_len > SPU_SSIZE_MAX) { errno = EINVAL; return -1; } sum += vec[i].iov_len; } return 0; } /** * default_posix1_handler_stat * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int stat(const char *file_name, struct stat *buf) */ static int default_posix1_handler_stat(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); struct stat buf; struct spe_compat_stat spe_buf; char *file_name; int rc; DEBUG_PRINTF("%s\n", __func__); file_name = GET_LS_PTR(arg0->slot[0]); rc = stat(file_name, &buf); if (rc == 0) { spe_buf.dev = buf.st_dev; spe_buf.ino = buf.st_ino; spe_buf.mode = buf.st_mode; spe_buf.nlink = buf.st_nlink; spe_buf.uid = buf.st_uid; spe_buf.gid = buf.st_gid; spe_buf.rdev = buf.st_rdev; spe_buf.size = buf.st_size; spe_buf.blksize = buf.st_blksize; spe_buf.blocks = buf.st_blocks; spe_buf.atime = buf.st_atime; spe_buf.mtime = buf.st_mtime; spe_buf.ctime = buf.st_ctime; memcpy(GET_LS_PTR(arg1->slot[0]), &spe_buf, sizeof(spe_buf)); } PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_fstat * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int fstat(int filedes, struct stat *buf) */ static int default_posix1_handler_fstat(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); struct stat buf; struct spe_compat_stat spe_buf; int filedes; int rc; DEBUG_PRINTF("%s\n", __func__); filedes = arg0->slot[0]; rc = fstat(filedes, &buf); if (rc == 0) { spe_buf.dev = buf.st_dev; spe_buf.ino = buf.st_ino; spe_buf.mode = buf.st_mode; spe_buf.nlink = buf.st_nlink; spe_buf.uid = buf.st_uid; spe_buf.gid = buf.st_gid; spe_buf.rdev = buf.st_rdev; spe_buf.size = buf.st_size; spe_buf.blksize = buf.st_blksize; spe_buf.blocks = buf.st_blocks; spe_buf.atime = buf.st_atime; spe_buf.mtime = buf.st_mtime; spe_buf.ctime = buf.st_ctime; memcpy(GET_LS_PTR(arg1->slot[0]), &spe_buf, sizeof(spe_buf)); } PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_lstat * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int lstat(const char *file_name, struct stat *buf) */ static int default_posix1_handler_lstat(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); struct stat buf; struct spe_compat_stat spe_buf; char *file_name; int rc; DEBUG_PRINTF("%s\n", __func__); file_name = GET_LS_PTR(arg0->slot[0]); rc = lstat(file_name, &buf); if (rc == 0) { spe_buf.dev = buf.st_dev; spe_buf.ino = buf.st_ino; spe_buf.mode = buf.st_mode; spe_buf.nlink = buf.st_nlink; spe_buf.uid = buf.st_uid; spe_buf.gid = buf.st_gid; spe_buf.rdev = buf.st_rdev; spe_buf.size = buf.st_size; spe_buf.blksize = buf.st_blksize; spe_buf.blocks = buf.st_blocks; spe_buf.atime = buf.st_atime; spe_buf.mtime = buf.st_mtime; spe_buf.ctime = buf.st_ctime; memcpy(GET_LS_PTR(arg1->slot[0]), &spe_buf, sizeof(spe_buf)); } PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_open * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int open(const char *pathname, int flags, mode_t mode); */ static int default_posix1_handler_open(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); char *pathname; int flags; mode_t mode; int rc; DEBUG_PRINTF("%s\n", __func__); pathname = GET_LS_PTR(arg0->slot[0]); flags = (int) arg1->slot[0]; mode = (mode_t) arg2->slot[0]; rc = open(pathname, flags, mode); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_access * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int access(const char *pathname, int mode); */ static int default_posix1_handler_access(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); char *pathname; int mode; int rc; DEBUG_PRINTF("%s\n", __func__); pathname = GET_LS_PTR(arg0->slot[0]); mode = (int) arg1->slot[0]; rc = access(pathname, mode); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_creat * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int creat(const char *pathname, mode_t mode); */ static int default_posix1_handler_creat(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); char *pathname; mode_t mode; int rc; DEBUG_PRINTF("%s\n", __func__); pathname = GET_LS_PTR(arg0->slot[0]); mode = (mode_t) arg1->slot[0]; rc = creat(pathname, mode); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_close * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int close(int fd); */ static int default_posix1_handler_close(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); int fd; int rc; DEBUG_PRINTF("%s\n", __func__); fd = arg0->slot[0]; rc = close(fd); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_dup * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int dup(int oldfd); */ static int default_posix1_handler_dup(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); int oldfd; int rc; DEBUG_PRINTF("%s\n", __func__); oldfd = arg0->slot[0]; rc = dup(oldfd); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_time * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * time_t time(time_t *t); */ static int default_posix1_handler_time(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); time_t *t; int rc; DEBUG_PRINTF("%s\n", __func__); t = GET_LS_PTR(arg0->slot[0]); rc = time(t); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_read * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * ssize_t read(int fd, void *buf, size_t count); */ static int default_posix1_handler_read(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); int fd; void *buf; size_t count; int rc; DEBUG_PRINTF("%s\n", __func__); fd = arg0->slot[0]; buf = GET_LS_PTR(arg1->slot[0]); count = arg2->slot[0]; rc = read(fd, buf, count); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_write * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * ssize_t write(int fd, const void *buf, size_t count); */ static int default_posix1_handler_write(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); int fd; void *buf; size_t count; int rc; DEBUG_PRINTF("%s\n", __func__); fd = arg0->slot[0]; buf = GET_LS_PTR(arg1->slot[0]); count = arg2->slot[0]; rc = write(fd, buf, count); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_lseek * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * off_t lseek(int fildes, off_t offset, int whence); */ static int default_posix1_handler_lseek(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); int fildes; off_t offset; int whence; int rc; DEBUG_PRINTF("%s\n", __func__); fildes = arg0->slot[0]; offset = (int) arg1->slot[0]; whence = arg2->slot[0]; rc = lseek(fildes, offset, whence); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_ftruncate * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int ftruncate(int fd, off_t length); * */ static int default_posix1_handler_ftruncate(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); int fd; off_t length; int rc; DEBUG_PRINTF("%s\n", __func__); fd = arg0->slot[0]; length = (int) arg1->slot[0]; rc = ftruncate(fd, length); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_unlink * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int unlink(const char *pathname); */ static int default_posix1_handler_unlink(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); char *pathname; int rc; DEBUG_PRINTF("%s\n", __func__); pathname = GET_LS_PTR(arg0->slot[0]); rc = unlink(pathname); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_mmap * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * void *mmap(void *start, size_t length, int prot , int flags, * int fd, off_t offset); * * Both 'start' and 'addr' (returned) are treated as 64b EA pointers * rather than LS offsets. On powerpc32 ABI (which is ILP-32), these * are handled as 32b EA pointers. */ static int default_posix1_handler_mmap(char *ls, unsigned long opdata) { DECL_6_ARGS(); DECL_RET(); addr64 start; size_t length; int prot; int flags; int fd; off_t offset; void *mmap_addr; addr64 addr; DEBUG_PRINTF("%s\n", __func__); start.by32[0] = arg0->slot[0]; start.by32[1] = arg0->slot[1]; length = (size_t) arg1->slot[0]; prot = arg2->slot[0]; flags = arg3->slot[0]; fd = arg4->slot[0]; offset = (int) arg5->slot[0]; mmap_addr = mmap((void *) ((unsigned long) start.all64), length, prot, flags, fd, offset); if (mmap_addr == MAP_FAILED) { addr.all64 = -1LL; } else { addr.all64 = (unsigned long long) (unsigned long) mmap_addr; } PUT_LS_RC(addr.by32[0], addr.by32[1], 0, errno); return 0; } /** * default_posix1_handler_munmap * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int munmap(void *start, size_t length); * * For this interface, 'start' is taken to be an EA pointer * rather than an LS offset. */ static int default_posix1_handler_munmap(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); addr64 start; size_t length; int rc; DEBUG_PRINTF("%s\n", __func__); start.by32[0] = arg0->slot[0]; start.by32[1] = arg0->slot[1]; length = (size_t) arg1->slot[0]; rc = munmap((void *) ((unsigned long) start.all64), length); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_mremap * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * void *mremap(void *old_address, size_t old_size, * size_t new_size, unsigned long flags); * * For this interface, both 'old_address' and the returned value * are taken to be EA pointers, rather than LS offsets. */ static int default_posix1_handler_mremap(char *ls, unsigned long opdata) { DECL_4_ARGS(); DECL_RET(); addr64 old_address; size_t old_size; size_t new_size; unsigned long flags; addr64 addr; DEBUG_PRINTF("%s\n", __func__); old_address.by32[0] = arg0->slot[0]; old_address.by32[1] = arg0->slot[1]; old_size = (size_t) arg1->slot[0]; new_size = (size_t) arg2->slot[0]; flags = (unsigned long) arg3->slot[0]; addr.all64 = (unsigned long) mremap((void *) ((unsigned long) old_address.all64), old_size, new_size, flags); PUT_LS_RC(addr.by32[0], addr.by32[1], 0, errno); return 0; } /** * default_posix1_handler_msync * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int msync(const void *start, size_t length, int flags); * * For this interface, 'start' is taken to be an EA pointer * rather than an LS offset. */ static int default_posix1_handler_msync(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); addr64 start; size_t length; int flags; int rc; DEBUG_PRINTF("%s\n", __func__); start.by32[0] = arg0->slot[0]; start.by32[1] = arg0->slot[1]; length = (size_t) arg1->slot[0]; flags = arg2->slot[0]; rc = msync((void *) ((unsigned long) start.all64), length, flags); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_shm_open * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * void *shm_open(const char *name, int oflag, mode_t mode); * * For this interface, the returned value is taken to be an * EA pointer rather than an LS offset. */ static int default_posix1_handler_shm_open(char *ls, unsigned long opdata) { #ifdef SPE_POSIX1_SHM_CALLS DECL_3_ARGS(); DECL_RET(); unsigned char *name; int oflag; mode_t mode; unsigned long addr; DEBUG_PRINTF("%s\n", __func__); name = GET_LS_PTR(arg0->slot[0]); oflag = (int) arg1->slot[0]; mode = (mode_t) arg2->slot[0]; addr = (unsigned long) shm_open(name, oflag, mode); PUT_LS_RC(addr, 0, 0, errno); #else DECL_0_ARGS(); DECL_RET(); PUT_LS_RC(-1, 0, 0, ENOSYS); #endif return 0; } /** * default_posix1_handler_shm_unlink * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int shm_unlink(const char *name); */ static int default_posix1_handler_shm_unlink(char *ls, unsigned long opdata) { #ifdef SPE_POSIX1_SHM_CALLS DECL_1_ARGS(); DECL_RET(); unsigned char *name; int rc; DEBUG_PRINTF("%s\n", __func__); name = GET_LS_PTR(arg0->slot[0]); rc = shm_unlink(name); PUT_LS_RC(rc, 0, 0, errno); #else DECL_0_ARGS(); DECL_RET(); PUT_LS_RC(-1, 0, 0, ENOSYS); #endif return 0; } /** * default_posix1_handler_shmat * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * void *shmat(int shmid, const void *shmaddr, int shmflg); * * For this interface, both 'shmaddr' and the returned value are * taken to be EA pointers rather than LS offsets. */ static int default_posix1_handler_shmat(char *ls, unsigned long opdata) { #ifdef SPE_POSIX1_SHM_CALLS DECL_3_ARGS(); DECL_RET(); int shmid; addr64 shmaddr; int shmflg; addr64 addr; DEBUG_PRINTF("%s\n", __func__); shmid = arg0->slot[0]; shmaddr.by32[0] = arg1->slot[0]; shmaddr.by32[1] = arg1->slot[1]; shmflg = arg2->slot[0]; addr.all64 = (unsigned long) shmat(shmid, (void *)((unsigned long)shmaddr.all64), shmflg); PUT_LS_RC(addr.by32[0], addr.by32[1], 0, errno); #else DECL_0_ARGS(); DECL_RET(); PUT_LS_RC(-1, 0, 0, ENOSYS); #endif return 0; } /** * default_posix1_handler_shmdt * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int shmdt(const void *shmaddr); * * For this interface 'shmaddr' is taken to be an EA pointer * rather than an LS offset. */ static int default_posix1_handler_shmdt(char *ls, unsigned long opdata) { #ifdef SPE_POSIX1_SHM_CALLS DECL_1_ARGS(); DECL_RET(); addr64 shmaddr; int rc; DEBUG_PRINTF("%s\n", __func__); shmaddr.by32[0] = arg0->slot[0]; shmaddr.by32[1] = arg0->slot[1]; rc = shmdt((void *) ((unsigned long) shmaddr.all64)); PUT_LS_RC(rc, 0, 0, errno); #else DECL_0_ARGS(); DECL_RET(); PUT_LS_RC(-1, 0, 0, ENOSYS); #endif return 0; } /** * default_posix1_handler_shmctl * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int shmctl(int shmid, int cmd, struct shmid_ds *buf); * * For this interface 'buf' is taken to be an EA pointer rather * than an LS offset. */ static int default_posix1_handler_shmctl(char *ls, unsigned long opdata) { #ifdef SPE_POSIX1_SHM_CALLS DECL_3_ARGS(); DECL_RET(); int shmid; int cmd; addr64 buf; int rc; DEBUG_PRINTF("%s\n", __func__); shmid = arg0->slot[0]; cmd = arg1->slot[0]; buf.by32[0] = arg2->slot[0]; buf.by32[1] = arg2->slot[1]; rc = shmctl(shmid, cmd, (struct shmid_ds *) ((unsigned long) buf.all64)); PUT_LS_RC(rc, 0, 0, errno); #else DECL_0_ARGS(); DECL_RET(); PUT_LS_RC(-1, 0, 0, ENOSYS); #endif return 0; } /** * default_posix1_handler_shmget * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int shmget(key_t key, int size, int shmflg); */ static int default_posix1_handler_shmget(char *ls, unsigned long opdata) { #ifdef SPE_POSIX1_SHM_CALLS DECL_3_ARGS(); DECL_RET(); key_t key; int size; int shmflg; int rc; DEBUG_PRINTF("%s\n", __func__); key = (key_t) arg0->slot[0]; size = arg1->slot[0]; shmflg = arg2->slot[0]; rc = shmget(key, size, shmflg); PUT_LS_RC(rc, 0, 0, errno); #else DECL_0_ARGS(); DECL_RET(); PUT_LS_RC(-1, 0, 0, ENOSYS); #endif return 0; } /** * default_posix1_handler_ftok * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * key_t ftok(const char *pathname, int proj_id); * * For convenience, this function takes 'pathname' to be the LS * offset of a NULL-terminated character string. */ static int default_posix1_handler_ftok(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); char *pathname; int proj_id; key_t rc; DEBUG_PRINTF("%s\n", __func__); pathname = GET_LS_PTR(arg0->slot[0]); proj_id = arg1->slot[0]; rc = ftok(pathname, proj_id); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_getpagesize * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int getpagesize(void); */ static int default_posix1_handler_getpagesize(char *ls, unsigned long opdata) { DECL_0_ARGS(); DECL_RET(); int sz; DEBUG_PRINTF("%s\n", __func__); sz = getpagesize(); PUT_LS_RC(sz, 0, 0, 0); return 0; } /** * default_posix1_handler_wait * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * pid_t wait(int *status) */ static int default_posix1_handler_wait(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); int *status; pid_t pid; DEBUG_PRINTF("%s\n", __func__); status = (int *) GET_LS_PTR(arg0->slot[0]); pid = wait(status); PUT_LS_RC(pid, 0, 0, errno); return 0; } /** * default_posix1_handler_waitpid * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * pid_t waitpid(pid_t pid, int *status, int options) */ static int default_posix1_handler_waitpid(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); pid_t pid; int *status; int options; DEBUG_PRINTF("%s\n", __func__); pid = arg0->slot[0]; status = (int *) GET_LS_PTR(arg1->slot[0]); options = arg2->slot[0]; pid = waitpid(pid, status, options); PUT_LS_RC(pid, 0, 0, errno); return 0; } /** * default_posix1_handler_kill * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int kill(pid_t pid, int sig) */ static int default_posix1_handler_kill(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); pid_t pid; int sig; int rc; DEBUG_PRINTF("%s\n", __func__); pid = arg0->slot[0]; sig = arg1->slot[0]; rc = kill(pid, sig); PUT_LS_RC(rc, 0, 0, errno); return 0; } #define _COPY_TIMEX_FIELD(_dst, _src, _field) \ (_dst)->_field = (_src)->_field #define _COPY_TIMEX_STRUCT(_dst, _src) \ _COPY_TIMEX_FIELD(_dst, _src, modes); \ _COPY_TIMEX_FIELD(_dst, _src, offset); \ _COPY_TIMEX_FIELD(_dst, _src, freq); \ _COPY_TIMEX_FIELD(_dst, _src, maxerror); \ _COPY_TIMEX_FIELD(_dst, _src, esterror); \ _COPY_TIMEX_FIELD(_dst, _src, status); \ _COPY_TIMEX_FIELD(_dst, _src, constant); \ _COPY_TIMEX_FIELD(_dst, _src, precision); \ _COPY_TIMEX_FIELD(_dst, _src, tolerance); \ _COPY_TIMEX_FIELD(_dst, _src, time.tv_sec); \ _COPY_TIMEX_FIELD(_dst, _src, time.tv_usec); \ _COPY_TIMEX_FIELD(_dst, _src, tick); \ _COPY_TIMEX_FIELD(_dst, _src, ppsfreq); \ _COPY_TIMEX_FIELD(_dst, _src, jitter); \ _COPY_TIMEX_FIELD(_dst, _src, shift); \ _COPY_TIMEX_FIELD(_dst, _src, stabil); \ _COPY_TIMEX_FIELD(_dst, _src, jitcnt); \ _COPY_TIMEX_FIELD(_dst, _src, calcnt); \ _COPY_TIMEX_FIELD(_dst, _src, errcnt); \ _COPY_TIMEX_FIELD(_dst, _src, stbcnt) /** * default_posix1_handler_adjtimex * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE adjtimex library operation: * * int adjtimex(struct timex *buf) */ static int default_posix1_handler_adjtimex(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); struct spe_compat_timex *buf; struct timex local; int rc; DEBUG_PRINTF("%s\n", __func__); buf = (struct spe_compat_timex *) GET_LS_PTR(arg0->slot[0]); _COPY_TIMEX_STRUCT(&local, buf); rc = adjtimex(&local); if (rc==0) { _COPY_TIMEX_STRUCT(buf, &local); } PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_gettimeofday * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int gettimeofday(struct timeval *tv, struct timezone *tz) */ static int default_posix1_handler_gettimeofday(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); struct spe_compat_timeval *tv; struct spe_compat_timezone *tz; struct timeval t; struct timezone zone; int rc; DEBUG_PRINTF("%s\n", __func__); tv = (struct spe_compat_timeval *) GET_LS_PTR(arg0->slot[0]); tz = (struct spe_compat_timezone *) GET_LS_PTR(arg1->slot[0]); rc = gettimeofday(&t, &zone); if (rc==0) { if (arg0->slot[0] != 0) { tv->tv_sec = t.tv_sec; tv->tv_usec = t.tv_usec; } if (arg1->slot[0] != 0) { tz->tz_minuteswest = zone.tz_minuteswest; } } PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_nanosleep * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * int nanosleep(struct timespec *req, struct timespec *rem); */ static int default_posix1_handler_nanosleep(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); struct spe_compat_timespec *spereq; struct spe_compat_timespec *sperem; struct timespec req; struct timespec rem, *remp; int rc; DEBUG_PRINTF("%s\n", __func__); spereq = GET_LS_PTR(arg0->slot[0]); req.tv_sec = spereq->tv_sec; req.tv_nsec = spereq->tv_nsec; if (arg1->slot[0] == 0) { sperem = NULL; remp = NULL; } else { sperem = GET_LS_PTR(arg1->slot[0]); remp = &rem; } rc = nanosleep(&req, remp); if (remp) { sperem->tv_sec = remp->tv_sec; sperem->tv_nsec = remp->tv_nsec; } PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_chdir * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * int chdir(const char *path) */ static int default_posix1_handler_chdir(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); char *path; int rc; DEBUG_PRINTF("%s\n", __func__); path = GET_LS_PTR(arg0->slot[0]); rc = chdir(path); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_fchdir * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * int fchdir(int fd) */ static int default_posix1_handler_fchdir(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); int fd; int rc; DEBUG_PRINTF("%s\n", __func__); fd = arg0->slot[0]; rc = fchdir(fd); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_mkdir * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * int mkdir(const char *pathname, mode_t mode) */ static int default_posix1_handler_mkdir(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); char *pathname; mode_t mode; int rc; DEBUG_PRINTF("%s\n", __func__); pathname = GET_LS_PTR(arg0->slot[0]); mode = arg1->slot[0]; rc = mkdir(pathname, mode); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_mknod * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * int mknod(const char *pathname, mode_t mode, dev_t dev) */ static int default_posix1_handler_mknod(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); char *pathname; mode_t mode; dev_t dev; int rc; DEBUG_PRINTF("%s\n", __func__); pathname = GET_LS_PTR(arg0->slot[0]); mode = arg1->slot[0]; dev = arg2->slot[0]; rc = mknod(pathname, mode, dev); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_rmdir * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * int rmdir(const char *pathname) */ static int default_posix1_handler_rmdir(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); char *pathname; int rc; DEBUG_PRINTF("%s\n", __func__); pathname = GET_LS_PTR(arg0->slot[0]); rc = rmdir(pathname); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_chmod * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * int chmod(const char *path, mode_t mode) */ static int default_posix1_handler_chmod(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); char *path; mode_t mode; int rc; DEBUG_PRINTF("%s\n", __func__); path = GET_LS_PTR(arg0->slot[0]); mode = arg1->slot[0]; rc = chmod(path, mode); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_fchmod * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * int fchmod(int fildes, mode_t mode) */ static int default_posix1_handler_fchmod(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); int filedes; mode_t mode; int rc; DEBUG_PRINTF("%s\n", __func__); filedes = arg0->slot[0]; mode = arg1->slot[0]; rc = fchmod(filedes, mode); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_chown * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * int chown(const char *path, uid_t owner, gid_t group) */ static int default_posix1_handler_chown(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); char *path; uid_t owner; gid_t group; int rc; DEBUG_PRINTF("%s\n", __func__); path = GET_LS_PTR(arg0->slot[0]); owner = arg1->slot[0]; group = arg2->slot[0]; rc = chown(path, owner, group); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_fchown * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * int fchown(int fd, uid_t owner, gid_t group) */ static int default_posix1_handler_fchown(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); int fd; uid_t owner; gid_t group; int rc; DEBUG_PRINTF("%s\n", __func__); fd = arg0->slot[0]; owner = arg1->slot[0]; group = arg2->slot[0]; rc = fchown(fd, owner, group); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_lchown * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * int lchown(const char *path, uid_t owner, gid_t group) */ static int default_posix1_handler_lchown(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); char *path; uid_t owner; gid_t group; int rc; DEBUG_PRINTF("%s\n", __func__); path = GET_LS_PTR(arg0->slot[0]); owner = arg1->slot[0]; group = arg2->slot[0]; rc = lchown(path, owner, group); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_getcwd * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * char *getcwd(char *buf, size_t size) */ static int default_posix1_handler_getcwd(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); char *buf; size_t size; char *res; int rc; DEBUG_PRINTF("%s\n", __func__); if (arg1->slot[0] == 0) { /* * Do not support a NULL buf, since any allocations need to take * place on the SPU. */ PUT_LS_RC(0, 0, 0, EINVAL); return 0; } buf = GET_LS_PTR(arg0->slot[0]); size = arg1->slot[0]; res = getcwd(buf, size); if (res == buf) { rc = arg0->slot[0]; } else { rc = 0; } PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_link * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * int link(const char *oldpath, const char *newpath) */ static int default_posix1_handler_link(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); char *oldpath; char *newpath; int rc; DEBUG_PRINTF("%s\n", __func__); oldpath = GET_LS_PTR(arg0->slot[0]); newpath = GET_LS_PTR(arg1->slot[0]); rc = link(oldpath, newpath); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_symlink * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * int symlink(const char *oldpath, const char *newpath) */ static int default_posix1_handler_symlink(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); char *oldpath; char *newpath; int rc; DEBUG_PRINTF("%s\n", __func__); oldpath = GET_LS_PTR(arg0->slot[0]); newpath = GET_LS_PTR(arg1->slot[0]); rc = symlink(oldpath, newpath); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_readlink * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * ssize_t readlink(const char *path, char *buf, size_t bufsiz) */ static int default_posix1_handler_readlink(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); char *path; char *buf; size_t bufsiz; int rc; DEBUG_PRINTF("%s\n", __func__); path = GET_LS_PTR(arg0->slot[0]); buf = GET_LS_PTR(arg1->slot[0]); bufsiz = arg2->slot[0]; rc = readlink(path, buf, bufsiz); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_sync * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * void sync(void) */ static int default_posix1_handler_sync(char *ls, unsigned long opdata) { DEBUG_PRINTF("%s\n", __func__); sync(); return 0; } /** * default_posix1_handler_fsync * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * int fsync(int fd) */ static int default_posix1_handler_fsync(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); int fd; int rc; DEBUG_PRINTF("%s\n", __func__); fd = arg0->slot[0]; rc = fsync(fd); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_fdatasync * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * int fdatasync(int fd) */ static int default_posix1_handler_fdatasync(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); int fd; int rc; DEBUG_PRINTF("%s\n", __func__); fd = arg0->slot[0]; rc = fdatasync(fd); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_dup2 * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * int dup2(int oldfd, int newfd) */ static int default_posix1_handler_dup2(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); int oldfd; int newfd; int rc; DEBUG_PRINTF("%s\n", __func__); oldfd = arg0->slot[0]; newfd = arg1->slot[0]; rc = dup2(oldfd, newfd); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_lockf * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * int lockf(int fd, int cmd, off_t len) */ static int default_posix1_handler_lockf(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); int fd; int cmd; off_t len; int rc; DEBUG_PRINTF("%s\n", __func__); fd = arg0->slot[0]; cmd = arg1->slot[0]; len = (int) arg2->slot[0]; rc = lockf(fd, cmd, len); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_truncate * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * int truncate(const char *path, off_t length) */ static int default_posix1_handler_truncate(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); char *path; off_t length; int rc; DEBUG_PRINTF("%s\n", __func__); path = GET_LS_PTR(arg0->slot[0]); length = (int) arg1->slot[0]; rc = truncate(path, length); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_mkstemp * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * int mkstemp(char *template) */ static int default_posix1_handler_mkstemp(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); char *template; int rc; DEBUG_PRINTF("%s\n", __func__); template = GET_LS_PTR(arg0->slot[0]); rc = mkstemp(template); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_mktemp * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * char *mktemp(char *template) */ static int default_posix1_handler_mktemp(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); char *template; int rc; DEBUG_PRINTF("%s\n", __func__); template = GET_LS_PTR(arg0->slot[0]); mktemp(template); /* * Note that POSIX says (and glibc implements) that mktemp always * returns the address of template, but the linux man page incorrectly * says (or said) NULL is returned on error. */ rc = arg0->slot[0]; PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_opendir * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * DIR *opendir(const char *dirname); */ static int default_posix1_handler_opendir(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); char *name; addr64 dir64; DIR *dir; DEBUG_PRINTF("%s\n", __func__); name = GET_LS_PTR(arg0->slot[0]); dir = opendir(name); dir64.all64 = spe_ptrto64(dir); PUT_LS_RC(dir64.by32[0], dir64.by32[1], 0, errno); return 0; } /** * default_posix1_handler_closedir * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * DIR *closedir(const char *dirname); */ static int default_posix1_handler_closedir(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); DIR *dir; int rc; DEBUG_PRINTF("%s\n", __func__); dir = spe_reg128toptr(arg0); rc = closedir(dir); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_readdir * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data, plus a secondary argument pass the * location of the dirent. * * Implement: * struct dirent *readdir(DIR *dir) */ static int default_posix1_handler_readdir(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); DIR *dir; struct dirent *ent; struct spe_compat_dirent *spe_ent; int rc; DEBUG_PRINTF("%s\n", __func__); dir = spe_reg128toptr(arg0); spe_ent = GET_LS_PTR(arg1->slot[0]); ent = readdir(dir); if (ent) { spe_copy_dirent(spe_ent, ent); rc = arg1->slot[0]; /* LS address of spe_ent */ } else { rc = 0; } PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_rewinddir * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data * * Implement: * void rewinddir(DIR *dir) */ static int default_posix1_handler_rewinddir(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); DIR *dir; DEBUG_PRINTF("%s\n", __func__); dir = spe_reg128toptr(arg0); rewinddir(dir); PUT_LS_RC(0, 0, 0, 0); return 0; } /** * default_posix1_handler_seekdir * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data * * Implement: * void seekdir(DIR *dir) */ static int default_posix1_handler_seekdir(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); DIR *dir; off_t offset; DEBUG_PRINTF("%s\n", __func__); dir = spe_reg128toptr(arg0); offset = (int) arg1->slot[0]; seekdir(dir, offset); PUT_LS_RC(0, 0, 0, 0); return 0; } /** * default_posix1_handler_telldir * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data * * Implement: */ static int default_posix1_handler_telldir(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); DIR *dir; int rc; DEBUG_PRINTF("%s\n", __func__); dir = spe_reg128toptr(arg0); rc = telldir(dir); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_sched_yield * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data * * Implement: * int sched_yield(void) */ static int default_posix1_handler_sched_yield(char *ls, unsigned long opdata) { DECL_0_ARGS(); DECL_RET(); /* * The kernel will call spu_yield internally, so do nothing here. */ DEBUG_PRINTF("%s\n", __func__); PUT_LS_RC(0, 0, 0, 0); return 0; } /** * default_posix1_handler_umask * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data * * Implement: * mode_t umask(mode_t mask) */ static int default_posix1_handler_umask(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); mode_t mask; int rc; DEBUG_PRINTF("%s\n", __func__); mask = arg0->slot[0]; rc = umask(mask); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_utime * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * int utime(const char *filename, const struct utimbuf *buf) */ static int default_posix1_handler_utime(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); char *filename; struct utimbuf buf; struct spe_compat_utimbuf *spebuf; int rc; DEBUG_PRINTF("%s\n", __func__); filename = GET_LS_PTR(arg0->slot[0]); spebuf = GET_LS_PTR(arg1->slot[0]); buf.actime = spebuf->actime; buf.modtime = spebuf->modtime; rc = utime(filename, &buf); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_utimes * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * int utimes(const char *filename, const struct timeval times[2]) */ static int default_posix1_handler_utimes(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); char *filename; struct spe_compat_timeval *spetimes; struct timeval times[2]; int rc; DEBUG_PRINTF("%s\n", __func__); filename = GET_LS_PTR(arg0->slot[0]); spetimes = GET_LS_PTR(arg1->slot[0]); times[0].tv_sec = spetimes[0].tv_sec; times[0].tv_usec = spetimes[0].tv_usec; times[1].tv_sec = spetimes[1].tv_sec; times[1].tv_usec = spetimes[1].tv_usec; rc = utimes(filename, times); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_pread * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * ssize_t pread(int fd, void *buf, size_t count, off_t offset) */ static int default_posix1_handler_pread(char *ls, unsigned long opdata) { DECL_4_ARGS(); DECL_RET(); int fd; void *buf; size_t count; off_t offset; int rc; DEBUG_PRINTF("%s\n", __func__); fd = arg0->slot[0]; buf = GET_LS_PTR(arg1->slot[0]); count = arg2->slot[0]; offset = (int) arg3->slot[0]; rc = pread(fd, buf, count, offset); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_pwrite * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset) */ static int default_posix1_handler_pwrite(char *ls, unsigned long opdata) { DECL_4_ARGS(); DECL_RET(); int fd; void *buf; size_t count; off_t offset; ssize_t sz; int rc; DEBUG_PRINTF("%s\n", __func__); fd = arg0->slot[0]; buf = GET_LS_PTR(arg1->slot[0]); count = arg2->slot[0]; offset = (int) arg3->slot[0]; sz = pwrite(fd, buf, count, offset); rc = sz; PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_readv * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * ssize_t readv(int fd, const struct iovec *vec, int count) */ static int default_posix1_handler_readv(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); int fd; struct iovec vec[IOV_MAX]; struct ls_iovec *lsvec; size_t count; int rc; DEBUG_PRINTF("%s\n", __func__); fd = arg0->slot[0]; lsvec = GET_LS_PTR(arg1->slot[0]); count = arg2->slot[0]; rc = check_conv_spuvec(ls, vec, lsvec, count); if (!rc) rc = readv(fd, vec, count); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_writev * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Implement: * ssize_t writev(int fd, const struct iovec *vec, int count) */ static int default_posix1_handler_writev(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); int fd; struct iovec vec[IOV_MAX]; struct ls_iovec *lsvec; size_t count; int rc; DEBUG_PRINTF("%s\n", __func__); fd = arg0->slot[0]; lsvec = GET_LS_PTR(arg1->slot[0]); count = arg2->slot[0]; rc = check_conv_spuvec(ls, vec, lsvec, count); if (!rc) rc = writev(fd, vec, count); PUT_LS_RC(rc, 0, 0, errno); return 0; } static int (*default_posix1_funcs[SPE_POSIX1_NR_OPCODES]) (char *, unsigned long) = { [SPE_POSIX1_UNUSED] = NULL, [SPE_POSIX1_ADJTIMEX] = default_posix1_handler_adjtimex, [SPE_POSIX1_CLOSE] = default_posix1_handler_close, [SPE_POSIX1_CREAT] = default_posix1_handler_creat, [SPE_POSIX1_FSTAT] = default_posix1_handler_fstat, [SPE_POSIX1_FTOK] = default_posix1_handler_ftok, [SPE_POSIX1_GETPAGESIZE] = default_posix1_handler_getpagesize, [SPE_POSIX1_GETTIMEOFDAY] = default_posix1_handler_gettimeofday, [SPE_POSIX1_KILL] = default_posix1_handler_kill, [SPE_POSIX1_LSEEK] = default_posix1_handler_lseek, [SPE_POSIX1_LSTAT] = default_posix1_handler_lstat, [SPE_POSIX1_MMAP] = default_posix1_handler_mmap, [SPE_POSIX1_MREMAP] = default_posix1_handler_mremap, [SPE_POSIX1_MSYNC] = default_posix1_handler_msync, [SPE_POSIX1_MUNMAP] = default_posix1_handler_munmap, [SPE_POSIX1_OPEN] = default_posix1_handler_open, [SPE_POSIX1_READ] = default_posix1_handler_read, [SPE_POSIX1_SHMAT] = default_posix1_handler_shmat, [SPE_POSIX1_SHMCTL] = default_posix1_handler_shmctl, [SPE_POSIX1_SHMDT] = default_posix1_handler_shmdt, [SPE_POSIX1_SHMGET] = default_posix1_handler_shmget, [SPE_POSIX1_SHM_OPEN] = default_posix1_handler_shm_open, [SPE_POSIX1_SHM_UNLINK] = default_posix1_handler_shm_unlink, [SPE_POSIX1_STAT] = default_posix1_handler_stat, [SPE_POSIX1_UNLINK] = default_posix1_handler_unlink, [SPE_POSIX1_WAIT] = default_posix1_handler_wait, [SPE_POSIX1_WAITPID] = default_posix1_handler_waitpid, [SPE_POSIX1_WRITE] = default_posix1_handler_write, [SPE_POSIX1_FTRUNCATE] = default_posix1_handler_ftruncate, [SPE_POSIX1_ACCESS] = default_posix1_handler_access, [SPE_POSIX1_DUP] = default_posix1_handler_dup, [SPE_POSIX1_TIME] = default_posix1_handler_time, [SPE_POSIX1_NANOSLEEP] = default_posix1_handler_nanosleep, [SPE_POSIX1_CHDIR] = default_posix1_handler_chdir, [SPE_POSIX1_FCHDIR] = default_posix1_handler_fchdir, [SPE_POSIX1_MKDIR] = default_posix1_handler_mkdir, [SPE_POSIX1_MKNOD] = default_posix1_handler_mknod, [SPE_POSIX1_RMDIR] = default_posix1_handler_rmdir, [SPE_POSIX1_CHMOD] = default_posix1_handler_chmod, [SPE_POSIX1_FCHMOD] = default_posix1_handler_fchmod, [SPE_POSIX1_CHOWN] = default_posix1_handler_chown, [SPE_POSIX1_FCHOWN] = default_posix1_handler_fchown, [SPE_POSIX1_LCHOWN] = default_posix1_handler_lchown, [SPE_POSIX1_GETCWD] = default_posix1_handler_getcwd, [SPE_POSIX1_LINK] = default_posix1_handler_link, [SPE_POSIX1_SYMLINK] = default_posix1_handler_symlink, [SPE_POSIX1_READLINK] = default_posix1_handler_readlink, [SPE_POSIX1_SYNC] = default_posix1_handler_sync, [SPE_POSIX1_FSYNC] = default_posix1_handler_fsync, [SPE_POSIX1_FDATASYNC] = default_posix1_handler_fdatasync, [SPE_POSIX1_DUP2] = default_posix1_handler_dup2, [SPE_POSIX1_LOCKF] = default_posix1_handler_lockf, [SPE_POSIX1_TRUNCATE] = default_posix1_handler_truncate, [SPE_POSIX1_MKSTEMP] = default_posix1_handler_mkstemp, [SPE_POSIX1_MKTEMP] = default_posix1_handler_mktemp, [SPE_POSIX1_OPENDIR] = default_posix1_handler_opendir, [SPE_POSIX1_CLOSEDIR] = default_posix1_handler_closedir, [SPE_POSIX1_READDIR] = default_posix1_handler_readdir, [SPE_POSIX1_REWINDDIR] = default_posix1_handler_rewinddir, [SPE_POSIX1_SEEKDIR] = default_posix1_handler_seekdir, [SPE_POSIX1_TELLDIR] = default_posix1_handler_telldir, [SPE_POSIX1_SCHED_YIELD] = default_posix1_handler_sched_yield, [SPE_POSIX1_UMASK] = default_posix1_handler_umask, [SPE_POSIX1_UTIME] = default_posix1_handler_utime, [SPE_POSIX1_UTIMES] = default_posix1_handler_utimes, [SPE_POSIX1_PREAD] = default_posix1_handler_pread, [SPE_POSIX1_PWRITE] = default_posix1_handler_pwrite, [SPE_POSIX1_READV] = default_posix1_handler_readv, [SPE_POSIX1_WRITEV] = default_posix1_handler_writev, }; /** * default_posix1_handler * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Default POSIX.1 call dispatch function. */ int _base_spe_default_posix1_handler(char *base, unsigned long offset) { int op, opdata; if (!base) { DEBUG_PRINTF("%s: mmap LS required.\n", __func__); return 1; } offset = (offset & LS_ADDR_MASK) & ~0x1; opdata = *((int *)((char *) base + offset)); op = SPE_POSIX1_OP(opdata); if ((op <= 0) || (op >= SPE_POSIX1_NR_OPCODES)) { DEBUG_PRINTF("%s: Unhandled type opdata=%08x op=%08x\n", __func__, opdata, SPE_POSIX1_OP(opdata)); return 1; } default_posix1_funcs[op] (base, opdata); return 0; } libspe2-2.2.80-95/spebase/run.c0000644000175100017510000002426310673437510015403 0ustar arthurarthur/* * libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #define GNU_SOURCE 1 #include #include #include #include #include #include #include #include #include #include #include "elf_loader.h" #include "lib_builtin.h" #include "spebase.h" /*Thread-local variable for use by the debugger*/ __thread struct spe_context_info { int spe_id; unsigned int npc; unsigned int status; struct spe_context_info *prev; }*__spe_current_active_context; static void cleanupspeinfo(struct spe_context_info *ctxinfo) { struct spe_context_info *tmp = ctxinfo->prev; __spe_current_active_context = tmp; } static int set_regs(struct spe_context *spe, void *regs) { int fd_regs, rc; fd_regs = openat(spe->base_private->fd_spe_dir, "regs", O_RDWR); if (fd_regs < 0) { DEBUG_PRINTF("Could not open SPE regs file.\n"); errno = EFAULT; return -1; } rc = write(fd_regs, regs, 2048); close(fd_regs); if (rc < 0) return -1; return 0; } static int issue_isolated_exit(struct spe_context *spe) { struct spe_spu_control_area *cntl_area = spe->base_private->cntl_mmap_base; if (cntl_area == MAP_FAILED) { DEBUG_PRINTF("%s: could not access SPE control area\n", __FUNCTION__); return -1; } /* 0x2 is an isolated exit request */ cntl_area->SPU_RunCntl = 0x2; return 0; } static inline void freespeinfo() { /*Clean up the debug variable*/ struct spe_context_info *tmp = __spe_current_active_context->prev; __spe_current_active_context = tmp; } 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 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; } libspe2-2.2.80-95/spebase/create.h0000644000175100017510000000210710650125273016033 0ustar arthurarthur/* * libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _create_h_ #define _create_h_ #include "spebase.h" extern int _base_spe_open_if_closed(struct spe_context *spe, enum fd_name fdesc, int locked); extern void _base_spe_close_if_open(struct spe_context *spe, enum fd_name fdesc); #endif libspe2-2.2.80-95/spebase/default_posix1_handler.h0000644000175100017510000000205310650126261021212 0ustar arthurarthur/* default_posix1_handler.h - emulate SPE C99 library calls. * * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __DEFAULT_POSIX1_HANDLER_H__ #define __DEFAULT_POSIX1_HANDLER_H__ #define SPE_POSIX1_CLASS 0x2101 extern int _base_spe_default_posix1_handler(char *ls, unsigned long args); #endif /* __DEFAULT_POSIX1_HANDLER_H__ */ libspe2-2.2.80-95/spebase/cbea_map.h0000644000175100017510000000457710600243027016325 0ustar arthurarthur/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _cbea_map_h_ #define _cbea_map_h_ #ifdef __cplusplus extern "C" { #endif /* spe problem state areas */ typedef struct spe_mssync_area { unsigned int MFC_MSSync; } spe_mssync_area_t; typedef struct spe_mfc_command_area { unsigned char reserved_0_3[4]; unsigned int MFC_LSA; unsigned int MFC_EAH; unsigned int MFC_EAL; unsigned int MFC_Size_Tag; union { unsigned int MFC_ClassID_CMD; unsigned int MFC_CMDStatus; }; unsigned char reserved_18_103[236]; unsigned int MFC_QStatus; unsigned char reserved_108_203[252]; unsigned int Prxy_QueryType; unsigned char reserved_208_21B[20]; unsigned int Prxy_QueryMask; unsigned char reserved_220_22B[12]; unsigned int Prxy_TagStatus; } spe_mfc_command_area_t; typedef struct spe_spu_control_area { unsigned char reserved_0_3[4]; unsigned int SPU_Out_Mbox; unsigned char reserved_8_B[4]; unsigned int SPU_In_Mbox; unsigned char reserved_10_13[4]; unsigned int SPU_Mbox_Stat; unsigned char reserved_18_1B[4]; unsigned int SPU_RunCntl; unsigned char reserved_20_23[4]; unsigned int SPU_Status; unsigned char reserved_28_33[12]; unsigned int SPU_NPC; } spe_spu_control_area_t; typedef struct spe_sig_notify_1_area { unsigned char reserved_0_B[12]; unsigned int SPU_Sig_Notify_1; } spe_sig_notify_1_area_t; typedef struct spe_sig_notify_2_area { unsigned char reserved_0_B[12]; unsigned int SPU_Sig_Notify_2; } spe_sig_notify_2_area_t; #ifdef __cplusplus } #endif #endif libspe2-2.2.80-95/spebase/default_libea_handler.c0000644000175100017510000001164010660060145021037 0ustar arthurarthur#define _GNU_SOURCE #include "default_libea_handler.h" #include "handler_utils.h" #include #include #include #include #include #include #include typedef union { unsigned long long all64; unsigned int by32[2]; } addr64; static inline size_t arg64_to_size_t(struct spe_reg128* arg0){ addr64 argument0; argument0.by32[0] = arg0->slot[0]; argument0.by32[1] = arg0->slot[1]; return (size_t)argument0.all64; } /** * default_libea_handler_calloc * @ls: base pointer to local store area. * @opdata: LIBEA call opcode & data. * * LIBEA library operation, per: upcoming RFC based on POSIX,C99 * implementing: * * void *calloc(size_t mnemb, size_t size); * * 'addr' (returned) is treated as a 64b EA pointer * rather than LS offset. On powerpc32 ABI (which is ILP-32), this * is handled as a 32b EA pointer. */ static int default_libea_handler_calloc(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); size_t nmemb; size_t size; void* calloc_addr = NULL; addr64 ret2; nmemb = arg64_to_size_t(arg0); size = arg64_to_size_t(arg1); /* OK, now if we are 32 bit and we were passed 64 bit that really was * bigger than 32 bit we need to bail. */ if((arg0->slot[0]== 0 && arg1->slot[0] == 0) || sizeof(nmemb) == 8) calloc_addr = calloc(nmemb, size); else errno = ENOMEM; ret2.all64 = (unsigned long long) (unsigned long) calloc_addr; PUT_LS_RC(ret2.by32[0], ret2.by32[1], 0, errno); return 0; } /** * default_libea_handler_free * @ls: base pointer to local store area. * @opdata: LIBEA call opcode & data. * * LIBEA library operation, per: upcoming RFC based on POSIX,C99 * implementing: * * void free(void* ptr); * * 'ptr' is treated as a 64b EA pointer * rather than LS offset. On powerpc32 ABI (which is ILP-32), this * is handled as a 32b EA pointer. */ static int default_libea_handler_free(char *ls, unsigned long opdata) { DECL_1_ARGS(); addr64 ptr; ptr.by32[0] = arg0->slot[0]; ptr.by32[1] = arg0->slot[1]; free((void *) ((unsigned long) ptr.all64)); return 0; } /** * default_libea_handler_malloc * @ls: base pointer to local store area. * @opdata: LIBEA call opcode & data. * * LIBEA library operation, per: upcoming RFC based on POSIX,C99 * implementing: * * void *malloc(size_t size); * * 'ret' (returned) is treated as a 64b EA pointer * rather than LS offset. On powerpc32 ABI (which is ILP-32), this * is handled as a 32b EA pointer. */ static int default_libea_handler_malloc(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); size_t size; void* malloc_addr = NULL; addr64 ret2; size = arg64_to_size_t(arg0); if(arg0->slot[0] == 0 || sizeof(size) == 8) malloc_addr = malloc(size); else errno = ENOMEM; ret2.all64 = (unsigned long long) (unsigned long) malloc_addr; PUT_LS_RC(ret2.by32[0], ret2.by32[1], 0, errno); return 0; } /** * default_libea_handler_realloc * @ls: base pointer to local store area. * @opdata: LIBEA call opcode & data. * * LIBEA library operation, per: upcoming RFC based on POSIX,C99 * implementing: * * void *realloc(void* ptr, size_t size); * * 'ptr' and 'ret' (returned) are treated as 64b EA pointers * rather than LS offsets. On powerpc32 ABI (which is ILP-32), this * is handled as a 32b EA pointer. */ static int default_libea_handler_realloc(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); addr64 ptr; size_t size; void* realloc_addr; addr64 ret2; ptr.by32[0] = arg0->slot[0]; ptr.by32[0] = arg0->slot[1]; size = arg64_to_size_t(arg1); if(arg1->slot[0] == 0 || sizeof(size) == 8) realloc_addr = realloc((void *) ((unsigned long)ptr.all64), size); else errno = ENOMEM; ret2.all64 = (unsigned long long) (unsigned long) realloc_addr; PUT_LS_RC(ret2.by32[0], ret2.by32[1], 0, errno); return 0; } static int (*default_libea_funcs[SPE_LIBEA_NR_OPCODES]) (char *, unsigned long) = { [SPE_LIBEA_UNUSED] = NULL, [SPE_LIBEA_CALLOC] = default_libea_handler_calloc, [SPE_LIBEA_FREE] = default_libea_handler_free, [SPE_LIBEA_MALLOC] = default_libea_handler_malloc, [SPE_LIBEA_REALLOC] = default_libea_handler_realloc, }; /** * default_libea_handler * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Default POSIX.1 call dispatch function. */ int _base_spe_default_libea_handler(char *base, unsigned long offset) { int op, opdata; if (!base) { DEBUG_PRINTF("%s: mmap LS required.\n", __func__); return 1; } offset = (offset & LS_ADDR_MASK) & ~0x1; opdata = *((int *)((char *) base + offset)); op = SPE_LIBEA_OP(opdata); if ((op <= 0) || (op >= SPE_LIBEA_NR_OPCODES)) { DEBUG_PRINTF("%s: Unhandled type opdata=%08x op=%08x\n", __func__, opdata, SPE_LIBEA_OP(opdata)); return 1; } default_libea_funcs[op] (base, opdata); return 0; } libspe2-2.2.80-95/spebase/handler_utils.h0000644000175100017510000000560410600243027017423 0ustar arthurarthur/* handler_utils.h - definitions for assisted SPE library calls. * * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __HANDLER_UTILS_H__ #define __HANDLER_UTILS_H__ struct spe_reg128 { unsigned int slot[4]; }; #ifndef LS_SIZE #define LS_SIZE 0x40000 /* 256K (in bytes) */ #define LS_ADDR_MASK (LS_SIZE - 1) #endif /* LS_SIZE */ #define __PRINTF(fmt, args...) { fprintf(stderr,fmt , ## args); } #ifdef DEBUG #define DEBUG_PRINTF(fmt, args...) __PRINTF(fmt , ## args) #else #define DEBUG_PRINTF(fmt, args...) #endif #define LS_ARG_ADDR(_index) \ (&((struct spe_reg128 *) ((char *) ls + ls_args))[_index]) #define DECL_RET() \ struct spe_reg128 *ret = LS_ARG_ADDR(0) #define GET_LS_PTR(_off) \ (void *) ((char *) ls + ((_off) & LS_ADDR_MASK)) #define GET_LS_PTR_NULL(_off) \ ((_off) ? GET_LS_PTR(_off) : NULL) #define DECL_0_ARGS() \ unsigned int ls_args = (opdata & 0xffffff) #define DECL_1_ARGS() \ DECL_0_ARGS(); \ struct spe_reg128 *arg0 = LS_ARG_ADDR(0) #define DECL_2_ARGS() \ DECL_1_ARGS(); \ struct spe_reg128 *arg1 = LS_ARG_ADDR(1) #define DECL_3_ARGS() \ DECL_2_ARGS(); \ struct spe_reg128 *arg2 = LS_ARG_ADDR(2) #define DECL_4_ARGS() \ DECL_3_ARGS(); \ struct spe_reg128 *arg3 = LS_ARG_ADDR(3) #define DECL_5_ARGS() \ DECL_4_ARGS(); \ struct spe_reg128 *arg4 = LS_ARG_ADDR(4) #define DECL_6_ARGS() \ DECL_5_ARGS(); \ struct spe_reg128 *arg5 = LS_ARG_ADDR(5) #define PUT_LS_RC(_a, _b, _c, _d) \ ret->slot[0] = (unsigned int) (_a); \ ret->slot[1] = (unsigned int) (_b); \ ret->slot[2] = (unsigned int) (_c); \ ret->slot[3] = (unsigned int) (_d); \ __asm__ __volatile__ ("sync" : : : "memory") #endif /* __HANDLER_UTILS_H__ */ libspe2-2.2.80-95/spebase/elf_loader.h0000644000175100017510000000310310650125723016661 0ustar arthurarthur/* * libspe2 - A wrapper library to adapt the JSRE SPE usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "spebase.h" #include #define LS_SIZE 0x40000 /* 256K (in bytes) */ #define SPE_LDR_PROG_start (LS_SIZE - 512) // location of spe_ld.so prog #define SPE_LDR_PARAMS_start (LS_SIZE - 128) // location of spe_ldr_params typedef union { unsigned long long ull; unsigned int ui[2]; } addr64; struct spe_ld_info { unsigned int entry; }; /* * Global API : */ int _base_spe_verify_spe_elf_image(spe_program_handle_t *handle); int _base_spe_load_spe_elf (spe_program_handle_t *handle, void *ld_buffer, struct spe_ld_info *ld_info); int _base_spe_parse_isolated_elf(spe_program_handle_t *handle, uint64_t *addr, uint32_t *size); int _base_spe_toe_ear (spe_program_handle_t *speh); libspe2-2.2.80-95/spebase/accessors.c0000644000175100017510000000477010650125273016560 0ustar arthurarthur/* * libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "spebase.h" #include "create.h" #include #include #include /* * accessor functions for private members */ void* _base_spe_ps_area_get(spe_context_ptr_t spe, enum ps_area area) { void *ptr; switch (area) { case SPE_MSSYNC_AREA: ptr = spe->base_private->mssync_mmap_base; break; case SPE_MFC_COMMAND_AREA: ptr = spe->base_private->mfc_mmap_base; break; case SPE_CONTROL_AREA: ptr = spe->base_private->cntl_mmap_base; break; case SPE_SIG_NOTIFY_1_AREA: ptr = spe->base_private->signal1_mmap_base; break; case SPE_SIG_NOTIFY_2_AREA: ptr = spe->base_private->signal2_mmap_base; break; default: errno = EINVAL; return NULL; break; } if (ptr == MAP_FAILED) { errno = EACCES; return NULL; } return ptr; } void* _base_spe_ls_area_get(spe_context_ptr_t spe) { return spe->base_private->mem_mmap_base; } __attribute__ ((noinline)) void __spe_context_update_event(void) { return; } int __base_spe_event_source_acquire(spe_context_ptr_t spe, enum fd_name fdesc) { return _base_spe_open_if_closed(spe, fdesc, 0); } void __base_spe_event_source_release(struct spe_context *spe, enum fd_name fdesc) { _base_spe_close_if_open(spe, fdesc); } int __base_spe_spe_dir_get(spe_context_ptr_t spe) { return spe->base_private->fd_spe_dir; } /** * speevent users read from this end */ int __base_spe_stop_event_source_get(spe_context_ptr_t spe) { return spe->base_private->ev_pipe[1]; } /** * speevent writes to this end */ int __base_spe_stop_event_target_get(spe_context_ptr_t spe) { return spe->base_private->ev_pipe[0]; } int _base_spe_ls_size_get(spe_context_ptr_t spe) { return LS_SIZE; } libspe2-2.2.80-95/spebase/default_c99_handler.c0000644000175100017510000014747510664524460020420 0ustar arthurarthur/* default_c99_handler.c - emulate SPE C99 library calls. * * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include "default_c99_handler.h" #include "handler_utils.h" /* SPE C99 Handlers - Overview: * This file implements handlers for SPE C99 library operations such * as printf(3) using standard C library facilities that are available * on the PPE. * * This approach optimizes for space over time. The local store footprint * of the SPE C99 library is reduced by handling file and string operations * on the PPE. This allows the programmer to reserve local store for high * compute intensity software, while still providing functional interfaces. * * The major drawback of this approach is performance. Since I/O is not * buffered on the SPE, application performance may suffer with repeated * calls to putc(3), for instance. Applications requiring high performance * buffered I/O should consider other solutions, such as NEWLIB. * * SPE-side Stubs: * The SPE-side of this interface is most likely implemented with a set of * assembly language stub routines. These are responsible for pushing SPE * register parameters onto the stack per the SPE-ABI, and then for executing * a stop-and-signal instruction with a reserved signal code * (currently 0x2100/SPE_PROGRAM_LIBRARY_CALL). * By convention, the next word following the stop-and-signal instruction * will contain the C99 op-code along with a pointer to the beginning of * the call stack frame. * * Variable argument library calls are converted side into equivilent va_list * form, i.e. printf(3) becomes vprintf(3) and scanf(3) becomes vscanf(3). This * conversion takes place within the SPE stub routines. * * PPE-Side Handlers: * The PPE application or library receives stop-and-signal notification * from the OS. The default_c99_handler() routine is then called in order * to parse the C99 op-code and branch to a specific C99 handler, such as * default_c99_handler_vprintf(). * * The C99 handlers use direct-mapped access to LS in order to fetch parameters * from the stack frame, and to place return values (including errno) into the * expected locations. */ #define SPE_C99_OP_SHIFT 24 #define SPE_C99_OP_MASK 0xff #define SPE_C99_DATA_MASK 0xffffff #define SPE_C99_OP(_v) (((_v) >> SPE_C99_OP_SHIFT) & SPE_C99_OP_MASK) #define SPE_C99_DATA(_v) ((_v) & SPE_C99_DATA_MASK) enum { SPE_C99_UNUSED, SPE_C99_CLEARERR, SPE_C99_FCLOSE, SPE_C99_FEOF, SPE_C99_FERROR, SPE_C99_FFLUSH, SPE_C99_FGETC, SPE_C99_FGETPOS, SPE_C99_FGETS, SPE_C99_FILENO, SPE_C99_FOPEN, SPE_C99_FPUTC, SPE_C99_FPUTS, SPE_C99_FREAD, SPE_C99_FREOPEN, SPE_C99_FSEEK, SPE_C99_FSETPOS, SPE_C99_FTELL, SPE_C99_FWRITE, SPE_C99_GETC, SPE_C99_GETCHAR, SPE_C99_GETS, SPE_C99_PERROR, SPE_C99_PUTC, SPE_C99_PUTCHAR, SPE_C99_PUTS, SPE_C99_REMOVE, SPE_C99_RENAME, SPE_C99_REWIND, SPE_C99_SETBUF, SPE_C99_SETVBUF, SPE_C99_SYSTEM, SPE_C99_TMPFILE, SPE_C99_TMPNAM, SPE_C99_UNGETC, SPE_C99_VFPRINTF, SPE_C99_VFSCANF, SPE_C99_VPRINTF, SPE_C99_VSCANF, SPE_C99_VSNPRINTF, SPE_C99_VSPRINTF, SPE_C99_VSSCANF, SPE_C99_LAST_OPCODE, }; #define SPE_C99_NR_OPCODES ((SPE_C99_LAST_OPCODE - SPE_C99_CLEARERR) + 1) #define SPE_STDIN 1 #define SPE_STDOUT 2 #define SPE_STDERR 3 #define SPE_FOPEN_MAX (FOPEN_MAX+1) #define SPE_FOPEN_MIN 4 #define SPE_STDIO_BUFSIZ 1024 /** * spe_FILE_ptrs - an indexed array of 'FILE *', used by SPE C99 calls. * * A layer of indirection to report back indices rather than 'FILE *', * so as to be type safe w/r/t the 64-bit PPC-ABI. * * The indices {0,1,2,3} are aliases to {NULL,stdin,stdout,stderr}. */ static pthread_mutex_t spe_c99_file_mutex = PTHREAD_MUTEX_INITIALIZER; static int nr_spe_FILE_ptrs = 3; static FILE *spe_FILE_ptrs[SPE_FOPEN_MAX] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; typedef unsigned long long __va_elem; /* Allocate stack space for vargs array. */ #define __VA_LIST_ALIGN 16UL #define __VA_LIST_ALLOCA(_nr) \ (__va_elem *)(((unsigned long)alloca((_nr+1) * sizeof(__va_elem) + __VA_LIST_ALIGN) \ + __VA_LIST_ALIGN - 1) & ~(__VA_LIST_ALIGN - 1)) #ifdef __powerpc64__ #define __VA_LIST_PUT(_vargs, _type, _a) \ ((_type *) ((unsigned long) _vargs + sizeof(__va_elem) - sizeof(_type)))[0] = (_a); \ _vargs = (__va_elem *)_vargs + 1 #define __VA_TEMP_ALLOCA(_nr) (struct __va_temp *) alloca((_nr+1) * sizeof(struct __va_temp)) #else /* !__powerpc64__ */ #define __OFFSET(_type) (sizeof(_type)-1) #define __MASK(_type) ~(__OFFSET(_type)) /* Align '_vargs' properly for '_type'. */ #define __VA_LIST_ALIGN_TO_TYPE(_vargs, _type) \ (((unsigned long) (_vargs) + __OFFSET(_type)) & __MASK(_type)) /* Put a value into the va_list pointed to by '_vargs'. */ #define __VA_LIST_PUT(_vargs, _type, _a) \ _vargs = (__va_elem *) __VA_LIST_ALIGN_TO_TYPE(_vargs, _type); \ ((_type *) _vargs)[0] = (_a); \ _vargs = (__va_elem *)(((_type *) _vargs) + 1) #define __VA_TEMP_ALLOCA(_nr) NULL /* unused */ #endif /* !__powerpc64__ */ #define GET_LS_VARG(_name) { \ memcpy(&(_name), GET_LS_PTR(spe_vlist->next_arg), sizeof(_name)); \ spe_vlist->next_arg += 16; \ if ((spe_vlist->next_arg & LS_ADDR_MASK) == \ (spe_vlist->caller_stack & LS_ADDR_MASK)) { \ spe_vlist->next_arg += 32; \ } \ } /* SPE va_list structure, * per SPU-ABI definition. */ struct spe_va_list { unsigned int next_arg; unsigned int pad0[3]; unsigned int caller_stack; unsigned int pad1[3]; }; #if !defined(__powerpc64__) /* PPC-32 va_list structure. * When nr is greater than 8, * called function takes parms * from 'ptr'. */ struct __ppc32_va_list { unsigned char nr_gpr; unsigned char nr_fpr; unsigned short reserved; void *ptr; }; #endif /* __powerpc64__ */ /* Temporary area to save long value or pointer on ppc64. */ struct __va_temp { long long llval; int *ptr; }; static int __do_vfprintf(FILE * stream, char *format, __va_elem * vlist) { #if !defined(__powerpc64__) struct __ppc32_va_list ap; ap.nr_gpr = 127; ap.nr_fpr = 127; ap.ptr = (void *) vlist; return vfprintf(stream, format, (void *) &ap); #else return vfprintf(stream, format, (void *) vlist); #endif } static int __do_vsprintf(char *string, char *format, __va_elem * vlist) { #if !defined(__powerpc64__) struct __ppc32_va_list ap; ap.nr_gpr = 127; ap.nr_fpr = 127; ap.ptr = (void *) vlist; return vsprintf(string, format, (void *) &ap); #else return vsprintf(string, format, (void *) vlist); #endif } static int __do_vsnprintf(char *string, size_t size, char *format, __va_elem * vlist) { #if !defined(__powerpc64__) struct __ppc32_va_list ap; ap.nr_gpr = 127; ap.nr_fpr = 127; ap.ptr = (void *) vlist; return vsnprintf(string, size, format, (void *) &ap); #else return vsnprintf(string, size, format, (void *) vlist); #endif } static int __do_vfscanf(FILE * stream, char *format, __va_elem * vlist) { #if !defined(__powerpc64__) struct __ppc32_va_list ap; ap.nr_gpr = 127; ap.nr_fpr = 127; ap.ptr = (void *) vlist; return vfscanf(stream, format, (void *) &ap); #else return vfscanf(stream, format, (void *) vlist); #endif } static int __do_vsscanf(char *string, char *format, __va_elem * vlist) { #if !defined(__powerpc64__) struct __ppc32_va_list ap; ap.nr_gpr = 127; ap.nr_fpr = 127; ap.ptr = (void *) vlist; return vsscanf(string, format, (void *) &ap); #else return vsscanf(string, format, (void *) vlist); #endif } #ifdef __powerpc64__ static void __copy_va_temp(struct __va_temp *vtemps) { while (vtemps->ptr) { *vtemps->ptr = vtemps->llval; vtemps++; } } #else /* !__powerpc64__ */ #define __copy_va_temp(vtemps) /* do nothing */ #endif /* __powerpc64__ */ static inline FILE *get_FILE_nolock(int nr) { FILE *ret; if (nr <= 0) { ret = NULL; } else if (nr >= SPE_FOPEN_MAX) { ret = NULL; } else { switch (nr) { case SPE_STDIN: ret = (spe_FILE_ptrs[1]) ? spe_FILE_ptrs[1] : stdin; break; case SPE_STDOUT: ret = (spe_FILE_ptrs[2]) ? spe_FILE_ptrs[2] : stdout; break; case SPE_STDERR: ret = (spe_FILE_ptrs[3]) ? spe_FILE_ptrs[3] : stderr; break; default: ret = spe_FILE_ptrs[nr]; break; } } return ret; } static inline FILE *get_FILE(int nr) { FILE *ret; pthread_mutex_lock(&spe_c99_file_mutex); ret = get_FILE_nolock(nr); pthread_mutex_unlock(&spe_c99_file_mutex); return ret; } #define SKIP_PRECISION(p, pr) { \ pr = 0; \ if (*p == '.') { \ switch (*++p) { \ case '0': \ case '1': \ case '2': \ case '3': \ case '4': \ case '5': \ case '6': \ case '7': \ case '8': \ case '9': \ while (*p && isdigit(*p)) p++; \ break; \ case '*': \ GET_LS_VARG(pr); \ __VA_LIST_PUT(vlist, int, pr); \ p++; \ break; \ default: \ break; \ } \ } \ } #define SKIP_FIELD_WIDTH(p, fw, output) { \ fw = 0; \ switch (*p) { \ case '0': \ case '1': \ case '2': \ case '3': \ case '4': \ case '5': \ case '6': \ case '7': \ case '8': \ case '9': \ while (*p && isdigit(*p)) p++; \ break; \ case '*': \ if (output) { \ GET_LS_VARG(fw); \ __VA_LIST_PUT(vlist, int, fw); \ } \ p++; \ break; \ default: \ break; \ } \ } #define SKIP_PRINTF_FLAG_CHARS(p) { \ int done = 0; \ do { \ switch (*p) { \ case '#': \ case '0': \ case '-': \ case '+': \ case ' ': \ p++; \ break; \ default: \ done = 1; \ break; \ } \ } while (!done); \ } #define SKIP_LENGTH_MODIFIERS(p, h, l) { \ int done = 0; \ h = 0; l = 0; \ do { \ switch (*p) { \ case 'h': \ h++; \ p++; \ break; \ case 'l': \ l++; \ p++; \ break; \ case 'j': \ l = 2; \ p++; \ break; \ case 'z': \ case 't': \ l = 1; \ p++; \ break; \ default: \ done = 1; \ break; \ } \ } while (!done); \ } #define COUNT_FIELD_WIDTH(p, output) { \ switch (*p) { \ case '0': \ case '1': \ case '2': \ case '3': \ case '4': \ case '5': \ case '6': \ case '7': \ case '8': \ case '9': \ while (*p && isdigit(*p)) p++; \ break; \ case '*': \ p++; \ if (output) nr++; \ break; \ default: \ break; \ } \ } #define COUNT_PRECISION(p, output) { \ if (*p == '.') { \ switch (*++p) { \ case '0': \ case '1': \ case '2': \ case '3': \ case '4': \ case '5': \ case '6': \ case '7': \ case '8': \ case '9': \ while (*p && isdigit(*p)) p++; \ break; \ case '*': \ if (output) nr++; \ p++; \ break; \ default: \ break; \ } \ } \ } #define SKIP_SCANF_FLAG_CHARS(p, sp) { \ int done = 0; \ sp = 0; \ do { \ switch (*p) { \ case '*': \ sp = 1; \ p++; \ break; \ default: \ done = 1; \ break; \ } \ } while (!done); \ } #define SKIP_CHAR_SET(p) \ { \ p++; \ if (*p == '^') p++; \ if (*p == ']') p++; \ p = strchr(p, ']'); \ if (p == NULL) { \ DEBUG_PRINTF("SKIP_CHAR_SET() error."); \ return 1; \ } \ } static int __nr_format_args(const char *format) { char *p; int nr = 0; for (p = (char *) format; *p; p++, nr++) { p = strchr(p, '%'); if (!p) { /* Done with formatting. */ break; } } /* Loosely estimate of the number of format arguments * by scanning for '%'. Multiply the return value by * 3 in order to account for variable format width or * precision. */ return nr * 3; } static int __parse_printf_format(char *ls, char *format, struct spe_va_list *spe_vlist, __va_elem * vlist, struct __va_temp *vtemps, int nr_vargs) { int fw, pr; int format_half, format_long; int ival; double dval; long long llval; unsigned int ls_offset; char *p; void *ptr; for (p = format; nr_vargs > 0 && *p; p++) { p = strchr(p, '%'); if (!p) { /* Done with formatting. */ break; } p++; nr_vargs--; SKIP_PRINTF_FLAG_CHARS(p); SKIP_FIELD_WIDTH(p, fw, 1); SKIP_PRECISION(p, pr); SKIP_LENGTH_MODIFIERS(p, format_half, format_long); switch (*p) { case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': if (format_long == 2) { GET_LS_VARG(llval); __VA_LIST_PUT(vlist, long long, llval); break; #ifdef __powerpc64__ } else if (format_long) { GET_LS_VARG(ival); switch (*p) { case 'd': case 'i': __VA_LIST_PUT(vlist, long, (long)ival); break; default: __VA_LIST_PUT(vlist, unsigned long, (unsigned long)(unsigned int)ival); break; } break; #endif /* __powerpc64__*/ } /* fall through */ case 'c': GET_LS_VARG(ival); __VA_LIST_PUT(vlist, int, ival); break; case 'a': case 'A': case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': GET_LS_VARG(dval); __VA_LIST_PUT(vlist, double, dval); break; case 'p': GET_LS_VARG(ival); __VA_LIST_PUT(vlist, unsigned long, (unsigned long)(unsigned int)ival); break; case 's': GET_LS_VARG(ls_offset); ptr = GET_LS_PTR(ls_offset); __VA_LIST_PUT(vlist, char *, ptr); break; case 'n': GET_LS_VARG(ls_offset); ptr = GET_LS_PTR(ls_offset); #ifdef __powerpc64__ if (format_long == 1) { vtemps->ptr = ptr; __VA_LIST_PUT(vlist, long long *, &vtemps->llval); vtemps++; break; } #endif /* __powerpc64__ */ __VA_LIST_PUT(vlist, void *, ptr); break; default: break; } } #ifdef __powerpc64__ vtemps->ptr = NULL; #endif /* __powerpc64__ */ return 0; } static int __parse_scanf_format(char *ls, char *format, struct spe_va_list *spe_vlist, __va_elem * vlist, struct __va_temp *vtemps, int nr_vargs) { int fw; int format_half, format_long, suppress; unsigned int ls_offset; char *p; void *ptr; for (p = format; nr_vargs > 0 && *p; p++) { p = strchr(p, '%'); if (!p) { /* No more formatting. */ break; } p++; nr_vargs--; SKIP_SCANF_FLAG_CHARS(p, suppress); SKIP_FIELD_WIDTH(p, fw, 0); SKIP_LENGTH_MODIFIERS(p, format_half, format_long); switch (*p) { case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': case 'n': #ifdef __powerpc64__ if (format_long == 1) { if (!suppress) { GET_LS_VARG(ls_offset); ptr = GET_LS_PTR(ls_offset); vtemps->ptr = ptr; __VA_LIST_PUT(vlist, long long *, &vtemps->llval); vtemps++; } break; } #endif /* __powerpc64__ */ /* fall through */ case 'a': case 'A': case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': case 'c': case 's': if (!suppress) { GET_LS_VARG(ls_offset); ptr = GET_LS_PTR(ls_offset); __VA_LIST_PUT(vlist, void *, ptr); } break; case 'p': if (!suppress) { #ifdef __powerpc64__ GET_LS_VARG(ls_offset); ptr = GET_LS_PTR(ls_offset); vtemps->ptr = ptr; __VA_LIST_PUT(vlist, long long *, &vtemps->llval); vtemps++; #else /* !__powerpc64__ */ GET_LS_VARG(ls_offset); ptr = GET_LS_PTR(ls_offset); __VA_LIST_PUT(vlist, int *, ptr); #endif /* !__powerpc64__ */ } break; case '[': SKIP_CHAR_SET(p); if (!suppress) { GET_LS_VARG(ls_offset); ptr = GET_LS_PTR(ls_offset); __VA_LIST_PUT(vlist, char *, ptr); } break; case '%': break; default: break; } } #ifdef __powerpc64__ vtemps->ptr = NULL; #endif /* __powerpc64__ */ return 0; } /** * default_c99_handler_remove * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int remove(const char *pathname); */ static int default_c99_handler_remove(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); char *path; int rc; DEBUG_PRINTF("%s\n", __func__); path = GET_LS_PTR(arg0->slot[0]); rc = remove(path); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_rename * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int rename(const char *oldname, const char *newname); */ static int default_c99_handler_rename(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); char *oldname; char *newname; int rc; DEBUG_PRINTF("%s\n", __func__); oldname = GET_LS_PTR(arg0->slot[0]); newname = GET_LS_PTR(arg1->slot[0]); rc = rename(oldname, newname); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_tmpfile * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * FILE *tmpfile(void); */ static int default_c99_handler_tmpfile(char *ls, unsigned long opdata) { DECL_0_ARGS(); DECL_RET(); int i; DEBUG_PRINTF("%s\n", __func__); if (nr_spe_FILE_ptrs >= SPE_FOPEN_MAX) { PUT_LS_RC(0, 0, 0, EMFILE); } else { for (i = SPE_FOPEN_MIN; i < SPE_FOPEN_MAX; i++) { if (spe_FILE_ptrs[i] == NULL) { spe_FILE_ptrs[i] = tmpfile(); if (spe_FILE_ptrs[i]) nr_spe_FILE_ptrs++; else i = 0; PUT_LS_RC(i, 0, 0, errno); break; } } if (i == SPE_FOPEN_MAX) { PUT_LS_RC(0, 0, 0, EMFILE); } } return 0; } /** * default_c99_handler_tmpnam * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * char *tmpnam(char *s); * * For integrity reasons we return failure. We should expose * mkstemp() instead. */ static int default_c99_handler_tmpnam(char *ls, unsigned long opdata) { DECL_0_ARGS(); DECL_RET(); DEBUG_PRINTF("%s\n", __func__); PUT_LS_RC(0, 0, 0, 0); return 0; } /** * default_c99_handler_fclose * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int fclose(FILE *stream); */ static int default_c99_handler_fclose(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); FILE *stream; int rc; DEBUG_PRINTF("%s\n", __func__); stream = get_FILE(arg0->slot[0]); pthread_mutex_lock(&spe_c99_file_mutex); rc = fclose(stream); if (rc == 0) { spe_FILE_ptrs[arg0->slot[0]] = NULL; nr_spe_FILE_ptrs--; } pthread_mutex_unlock(&spe_c99_file_mutex); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_fflush * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int fflush(FILE *stream); */ static int default_c99_handler_fflush(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); FILE *stream; int rc; DEBUG_PRINTF("%s\n", __func__); stream = get_FILE(arg0->slot[0]); rc = fflush(stream); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_fopen * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * FILE *fopen(const char *path, const char *mode); */ static int default_c99_handler_fopen(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); char *path; char *mode; FILE *f; int i, rc = 0, err = EMFILE; DEBUG_PRINTF("%s\n", __func__); path = GET_LS_PTR(arg0->slot[0]); mode = GET_LS_PTR(arg1->slot[0]); pthread_mutex_lock(&spe_c99_file_mutex); if (nr_spe_FILE_ptrs < SPE_FOPEN_MAX) { for (i = SPE_FOPEN_MIN; i < SPE_FOPEN_MAX; i++) { if (spe_FILE_ptrs[i] == NULL) { f = fopen(path, mode); err = errno; if (f) { spe_FILE_ptrs[i] = f; nr_spe_FILE_ptrs++; rc = i; } break; } } } pthread_mutex_unlock(&spe_c99_file_mutex); PUT_LS_RC(rc, 0, 0, err); return 0; } /** * default_c99_handler_freopen * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * FILE *freopen(const char *path, const char *mode, FILE *stream); */ static int default_c99_handler_freopen(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); char *path; char *mode; int i; DEBUG_PRINTF("%s\n", __func__); i = arg2->slot[0]; if ((i <= 0) || (i >= SPE_FOPEN_MAX)) { PUT_LS_RC(1, 0, 0, EBADF); } else { path = GET_LS_PTR(arg0->slot[0]); mode = GET_LS_PTR(arg1->slot[0]); pthread_mutex_lock(&spe_c99_file_mutex); spe_FILE_ptrs[i] = freopen(path, mode, get_FILE_nolock(i)); if (spe_FILE_ptrs[i]) { PUT_LS_RC(i, 0, 0, 0); } else { PUT_LS_RC(0, 0, 0, errno); } pthread_mutex_unlock(&spe_c99_file_mutex); } return 0; } /** * default_c99_handler_setbuf * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * void setbuf(FILE *stream, char *buf); */ static int default_c99_handler_setbuf(char *ls, unsigned long opdata) { DECL_2_ARGS(); FILE *stream; char *buf; DEBUG_PRINTF("%s\n", __func__); stream = get_FILE(arg0->slot[0]); buf = GET_LS_PTR_NULL(arg1->slot[0]); setvbuf(stream, buf, buf ? _IOFBF : _IONBF, SPE_STDIO_BUFSIZ); return 0; } /** * default_c99_handler_setvbuf * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int setvbuf(FILE *stream, char *buf, int mode , size_t size); */ static int default_c99_handler_setvbuf(char *ls, unsigned long opdata) { DECL_4_ARGS(); DECL_RET(); FILE *stream; char *buf; int mode; size_t size; int rc; DEBUG_PRINTF("%s\n", __func__); stream = get_FILE(arg0->slot[0]); buf = GET_LS_PTR_NULL(arg1->slot[0]); mode = arg2->slot[0]; size = arg3->slot[0]; rc = setvbuf(stream, buf, mode, size); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_vfprintf * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int vfprintf(FILE *stream, const char *format, va_list ap); */ static int default_c99_handler_vfprintf(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); FILE *stream; char *format; int rc, nr_vargs; struct spe_va_list spe_vlist; __va_elem *vlist; struct __va_temp *vtemps; /* for %n in 64-bit PPC-ABI */ DEBUG_PRINTF("%s\n", __func__); stream = get_FILE(arg0->slot[0]); format = GET_LS_PTR(arg1->slot[0]); memcpy(&spe_vlist, arg2, sizeof(struct spe_va_list)); nr_vargs = __nr_format_args(format); vlist = __VA_LIST_ALLOCA(nr_vargs); vtemps = __VA_TEMP_ALLOCA(nr_vargs); rc = __parse_printf_format(ls, format, &spe_vlist, vlist, vtemps, nr_vargs); if (rc == 0) { rc = __do_vfprintf(stream, format, vlist); __copy_va_temp(vtemps); } else { rc = -1; } PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_vfscanf * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int vfscanf(FILE *stream, const char *format, va_list ap); */ static int default_c99_handler_vfscanf(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); FILE *stream; char *format; int rc, nr_vargs; struct spe_va_list spe_vlist; __va_elem *vlist; struct __va_temp *vtemps; DEBUG_PRINTF("%s\n", __func__); stream = get_FILE(arg0->slot[0]); format = GET_LS_PTR(arg1->slot[0]); memcpy(&spe_vlist, arg2, sizeof(struct spe_va_list)); nr_vargs = __nr_format_args(format); vlist = __VA_LIST_ALLOCA(nr_vargs); vtemps = __VA_TEMP_ALLOCA(nr_vargs); rc = __parse_scanf_format(ls, format, &spe_vlist, vlist, vtemps, nr_vargs); if (rc == 0) { rc = __do_vfscanf(stream, format, vlist); __copy_va_temp(vtemps); } else { rc = EOF; } PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_vprintf * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int vprintf(const char *format, va_list ap); */ static int default_c99_handler_vprintf(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); FILE *stream; char *format; int rc, nr_vargs; struct spe_va_list spe_vlist; __va_elem *vlist; struct __va_temp *vtemps; /* for %n in 64-bit PPC-ABI */ DEBUG_PRINTF("%s\n", __func__); stream = get_FILE(SPE_STDOUT); format = GET_LS_PTR(arg0->slot[0]); memcpy(&spe_vlist, arg1, sizeof(struct spe_va_list)); nr_vargs = __nr_format_args(format); vlist = __VA_LIST_ALLOCA(nr_vargs); vtemps = __VA_TEMP_ALLOCA(nr_vargs); rc = __parse_printf_format(ls, format, &spe_vlist, vlist, vtemps, nr_vargs); if (rc == 0) { rc = __do_vfprintf(stream, format, vlist); __copy_va_temp(vtemps); } else { rc = -1; } PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_vscanf * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int vscanf(const char *format, va_list ap); */ static int default_c99_handler_vscanf(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); FILE *stream; char *format; int rc, nr_vargs; struct spe_va_list spe_vlist; __va_elem *vlist; struct __va_temp *vtemps; DEBUG_PRINTF("%s\n", __func__); stream = get_FILE(SPE_STDIN); format = GET_LS_PTR(arg0->slot[0]); memcpy(&spe_vlist, arg1, sizeof(struct spe_va_list)); nr_vargs = __nr_format_args(format); vlist = __VA_LIST_ALLOCA(nr_vargs); vtemps = __VA_TEMP_ALLOCA(nr_vargs); rc = __parse_scanf_format(ls, format, &spe_vlist, vlist, vtemps, nr_vargs); if (rc == 0) { rc = __do_vfscanf(stream, format, vlist); __copy_va_temp(vtemps); } else { rc = EOF; } PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_vsnprintf * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int vsnprintf(char *str, size_t size, const char *format, va_list ap); */ static int default_c99_handler_vsnprintf(char *ls, unsigned long opdata) { DECL_4_ARGS(); DECL_RET(); char *str; char *format; size_t size; int rc, nr_vargs; struct spe_va_list spe_vlist; __va_elem *vlist; struct __va_temp *vtemps; /* for %n in 64-bit PPC-ABI */ DEBUG_PRINTF("%s\n", __func__); str = GET_LS_PTR(arg0->slot[0]); size = arg1->slot[0]; format = GET_LS_PTR(arg2->slot[0]); memcpy(&spe_vlist, arg3, sizeof(struct spe_va_list)); nr_vargs = __nr_format_args(format); vlist = __VA_LIST_ALLOCA(nr_vargs); vtemps = __VA_TEMP_ALLOCA(nr_vargs); rc = __parse_printf_format(ls, format, &spe_vlist, vlist, vtemps, nr_vargs); if (rc == 0) { rc = __do_vsnprintf(str, size, format, vlist); __copy_va_temp(vtemps); } else { rc = -1; } PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_vsprintf * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int vsprintf(char *str, const char *format, va_list ap); */ static int default_c99_handler_vsprintf(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); char *str; char *format; int rc, nr_vargs; struct spe_va_list spe_vlist; __va_elem *vlist; struct __va_temp *vtemps; /* for %n in 64-bit PPC-ABI */ DEBUG_PRINTF("%s\n", __func__); str = GET_LS_PTR(arg0->slot[0]); format = GET_LS_PTR(arg1->slot[0]); memcpy(&spe_vlist, arg2, sizeof(struct spe_va_list)); nr_vargs = __nr_format_args(format); vlist = __VA_LIST_ALLOCA(nr_vargs); vtemps = __VA_TEMP_ALLOCA(nr_vargs); rc = __parse_printf_format(ls, format, &spe_vlist, vlist, vtemps, nr_vargs); if (rc == 0) { rc = __do_vsprintf(str, format, vlist); __copy_va_temp(vtemps); } else { rc = -1; } PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_vsscanf * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int vsscanf(const char *str, const char *format, va_list ap); */ static int default_c99_handler_vsscanf(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); char *str; char *format; int rc, nr_vargs; struct spe_va_list spe_vlist; __va_elem *vlist; struct __va_temp *vtemps; DEBUG_PRINTF("%s\n", __func__); str = GET_LS_PTR(arg0->slot[0]); format = GET_LS_PTR(arg1->slot[0]); memcpy(&spe_vlist, arg2, sizeof(struct spe_va_list)); nr_vargs = __nr_format_args(format); vlist = __VA_LIST_ALLOCA(nr_vargs); vtemps = __VA_TEMP_ALLOCA(nr_vargs); rc = __parse_scanf_format(ls, format, &spe_vlist, vlist, vtemps, nr_vargs); if (rc == 0) { rc = __do_vsscanf(str, format, vlist); __copy_va_temp(vtemps); } else { rc = EOF; } PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_fgetc * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int fgetc(FILE *stream); */ static int default_c99_handler_fgetc(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); FILE *stream; int rc; DEBUG_PRINTF("%s\n", __func__); stream = get_FILE(arg0->slot[0]); rc = fgetc(stream); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_fgets * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * char *fgets(char *s, int size, FILE *stream); */ static int default_c99_handler_fgets(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); char *s; FILE *stream; int size; int rc; DEBUG_PRINTF("%s\n", __func__); s = GET_LS_PTR(arg0->slot[0]); size = arg1->slot[0]; stream = get_FILE(arg2->slot[0]); rc = (fgets(s, size, stream) == s) ? arg0->slot[0] : 0; PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_fileno * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE library operation, implementing: * * int fileno(FILE *stream); */ static int default_c99_handler_fileno(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); FILE *stream; int rc; DEBUG_PRINTF("%s\n", __func__); stream = get_FILE(arg0->slot[0]); rc = fileno(stream); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_fputc * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int fputc(int c, FILE *stream); */ static int default_c99_handler_fputc(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); FILE *stream; int c; int rc; DEBUG_PRINTF("%s\n", __func__); c = arg0->slot[0]; stream = get_FILE(arg1->slot[0]); rc = fputc(c, stream); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_fputs * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int fputs(const char *s, FILE *stream); */ static int default_c99_handler_fputs(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); char *s; FILE *stream; int rc; DEBUG_PRINTF("%s\n", __func__); s = GET_LS_PTR(arg0->slot[0]); stream = get_FILE(arg1->slot[0]); rc = fputs(s, stream); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_getc * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int getc(FILE *stream); */ static int default_c99_handler_getc(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); FILE *stream; int rc; DEBUG_PRINTF("%s\n", __func__); stream = get_FILE(arg0->slot[0]); rc = getc(stream); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_getchar * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int getchar(void); */ static int default_c99_handler_getchar(char *ls, unsigned long opdata) { DECL_0_ARGS(); DECL_RET(); FILE *stream; int rc; DEBUG_PRINTF("%s\n", __func__); stream = get_FILE(SPE_STDIN); rc = getc(stream); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_gets * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * char *gets(char *s); * * Implementation note: gets() is a classic security/integrity * hole, since its impossible to tell how many characters will * be input. */ static int default_c99_handler_gets(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); FILE *stream; char *s, *r; int rc; int size; DEBUG_PRINTF("%s\n", __func__); stream = get_FILE(SPE_STDIN); s = GET_LS_PTR(arg0->slot[0]); size = LS_SIZE - arg0->slot[0]; r = fgets(s, size, stream); rc = (r == s) ? arg0->slot[0] : 0; if (r == s) { /* remove trailing linefeed character. */ char *p = s + strlen(s); if (p > s && p[-1] == '\n') p[-1] = '\0'; } PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_putc * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int putc(int c, FILE *stream); */ static int default_c99_handler_putc(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); FILE *f; int rc; DEBUG_PRINTF("%s\n", __func__); f = get_FILE(arg1->slot[0]); rc = putc(arg0->slot[0], f); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_putchar * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int putchar(int c); */ static int default_c99_handler_putchar(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); FILE *stream; int rc; DEBUG_PRINTF("%s\n", __func__); stream = get_FILE(SPE_STDOUT); rc = putc(arg0->slot[0], stream); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_puts * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int puts(const char *s); */ static int default_c99_handler_puts(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); char *s; int rc; DEBUG_PRINTF("%s\n", __func__); s = GET_LS_PTR(arg0->slot[0]); rc = puts(s); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_ungetc * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int ungetc(int c, FILE *stream); */ static int default_c99_handler_ungetc(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); FILE *stream; int rc, c; DEBUG_PRINTF("%s\n", __func__); c = arg0->slot[0]; stream = get_FILE(arg1->slot[0]); rc = ungetc(c, stream); PUT_LS_RC(rc, 0, 0, 0); return 0; } /** * default_c99_handler_fread * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); */ static int default_c99_handler_fread(char *ls, unsigned long opdata) { DECL_4_ARGS(); DECL_RET(); void *ptr; size_t size, nmemb; FILE *stream; int rc = 0; DEBUG_PRINTF("%s\n", __func__); ptr = GET_LS_PTR(arg0->slot[0]); size = arg1->slot[0]; nmemb = arg2->slot[0]; stream = get_FILE(arg3->slot[0]); rc = fread(ptr, size, nmemb, stream); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_fwrite * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); */ static int default_c99_handler_fwrite(char *ls, unsigned long opdata) { DECL_4_ARGS(); DECL_RET(); void *ptr; size_t size, nmemb; FILE *stream; int rc; DEBUG_PRINTF("%s\n", __func__); ptr = GET_LS_PTR(arg0->slot[0]); size = arg1->slot[0]; nmemb = arg2->slot[0]; stream = get_FILE(arg3->slot[0]); rc = fwrite(ptr, size, nmemb, stream); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_fgetpos * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int fgetpos(FILE *stream, fpos_t *pos); */ static int default_c99_handler_fgetpos(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); FILE *stream; fpos_t *pos; int rc; DEBUG_PRINTF("%s\n", __func__); stream = get_FILE(arg0->slot[0]); pos = (fpos_t *) GET_LS_PTR(arg1->slot[0]); rc = fgetpos(stream, pos); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_fseek * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int fseek(FILE *stream, long offset, int whence); */ static int default_c99_handler_fseek(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); FILE *stream; long offset; int whence; int rc; DEBUG_PRINTF("%s\n", __func__); stream = get_FILE(arg0->slot[0]); offset = (long) arg1->slot[0]; whence = arg2->slot[0]; rc = fseek(stream, offset, whence); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_fsetpos * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int fsetpos(FILE *stream, fpos_t *pos); */ static int default_c99_handler_fsetpos(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); FILE *stream; fpos_t *pos; int rc; DEBUG_PRINTF("%s\n", __func__); stream = get_FILE(arg0->slot[0]); pos = (fpos_t *) GET_LS_PTR(arg1->slot[0]); rc = fsetpos(stream, pos); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_ftell * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * long ftell(FILE *stream); */ static int default_c99_handler_ftell(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); FILE *stream; int rc; DEBUG_PRINTF("%s\n", __func__); stream = get_FILE(arg0->slot[0]); rc = ftell(stream); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_rewind * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * void rewind(FILE *stream); */ static int default_c99_handler_rewind(char *ls, unsigned long opdata) { DECL_1_ARGS(); FILE *stream; DEBUG_PRINTF("%s\n", __func__); stream = get_FILE(arg0->slot[0]); rewind(stream); return 0; } /** * default_c99_handler_clearerr * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * void clearerr(FILE *stream); */ static int default_c99_handler_clearerr(char *ls, unsigned long opdata) { DECL_1_ARGS(); FILE *stream; DEBUG_PRINTF("%s\n", __func__); stream = get_FILE(arg0->slot[0]); clearerr(stream); return 0; } /** * default_c99_handler_feof * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int feof(FILE *stream); */ static int default_c99_handler_feof(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); FILE *stream; int rc; DEBUG_PRINTF("%s\n", __func__); stream = get_FILE(arg0->slot[0]); rc = feof(stream); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_ferror * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * void ferror(FILE *stream); */ static int default_c99_handler_ferror(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); FILE *stream; int rc; DEBUG_PRINTF("%s\n", __func__); stream = get_FILE(arg0->slot[0]); rc = ferror(stream); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_perror * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data, plus the value of errno on the SPU * must be passed. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * void perror(const char *s); */ static int default_c99_handler_perror(char *ls, unsigned long opdata) { DECL_2_ARGS(); char *s; DEBUG_PRINTF("%s\n", __func__); s = GET_LS_PTR_NULL(arg0->slot[0]); errno = arg1->slot[0]; /* * Older versions did not pass errno, so using older SPU newlib with * current libspe will likely give ouput like "Unknown error 262016". */ perror(s); return 0; } /** * default_c99_handler_system * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int system(const char *string); */ static int default_c99_handler_system(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); char *string; int rc; DEBUG_PRINTF("%s\n", __func__); string = GET_LS_PTR(arg0->slot[0]); rc = system(string); PUT_LS_RC(rc, 0, 0, errno); return 0; } static int (*default_c99_funcs[SPE_C99_NR_OPCODES]) (char *, unsigned long) = { [SPE_C99_UNUSED] = NULL, [SPE_C99_CLEARERR] = default_c99_handler_clearerr, [SPE_C99_FCLOSE] = default_c99_handler_fclose, [SPE_C99_FEOF] = default_c99_handler_feof, [SPE_C99_FERROR] = default_c99_handler_ferror, [SPE_C99_FFLUSH] = default_c99_handler_fflush, [SPE_C99_FGETC] = default_c99_handler_fgetc, [SPE_C99_FGETPOS] = default_c99_handler_fgetpos, [SPE_C99_FGETS] = default_c99_handler_fgets, [SPE_C99_FILENO] = default_c99_handler_fileno, [SPE_C99_FOPEN] = default_c99_handler_fopen, [SPE_C99_FPUTC] = default_c99_handler_fputc, [SPE_C99_FPUTS] = default_c99_handler_fputs, [SPE_C99_FREAD] = default_c99_handler_fread, [SPE_C99_FREOPEN] = default_c99_handler_freopen, [SPE_C99_FSEEK] = default_c99_handler_fseek, [SPE_C99_FSETPOS] = default_c99_handler_fsetpos, [SPE_C99_FTELL] = default_c99_handler_ftell, [SPE_C99_FWRITE] = default_c99_handler_fwrite, [SPE_C99_GETC] = default_c99_handler_getc, [SPE_C99_GETCHAR] = default_c99_handler_getchar, [SPE_C99_GETS] = default_c99_handler_gets, [SPE_C99_PERROR] = default_c99_handler_perror, [SPE_C99_PUTC] = default_c99_handler_putc, [SPE_C99_PUTCHAR] = default_c99_handler_putchar, [SPE_C99_PUTS] = default_c99_handler_puts, [SPE_C99_REMOVE] = default_c99_handler_remove, [SPE_C99_RENAME] = default_c99_handler_rename, [SPE_C99_REWIND] = default_c99_handler_rewind, [SPE_C99_SETBUF] = default_c99_handler_setbuf, [SPE_C99_SETVBUF] = default_c99_handler_setvbuf, [SPE_C99_SYSTEM] = default_c99_handler_system, [SPE_C99_TMPFILE] = default_c99_handler_tmpfile, [SPE_C99_TMPNAM] = default_c99_handler_tmpnam, [SPE_C99_UNGETC] = default_c99_handler_ungetc, [SPE_C99_VFPRINTF] = default_c99_handler_vfprintf, [SPE_C99_VFSCANF] = default_c99_handler_vfscanf, [SPE_C99_VPRINTF] = default_c99_handler_vprintf, [SPE_C99_VSCANF] = default_c99_handler_vscanf, [SPE_C99_VSNPRINTF] = default_c99_handler_vsnprintf, [SPE_C99_VSPRINTF] = default_c99_handler_vsprintf, [SPE_C99_VSSCANF] = default_c99_handler_vsscanf, }; /** * default_c99_handler * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * Top-level dispatch for SPE C99 library operations. */ int _base_spe_default_c99_handler(unsigned long *base, unsigned long offset) { int op, opdata; if (!base) { DEBUG_PRINTF("%s: mmap LS required.\n", __func__); return 1; } offset = (offset & LS_ADDR_MASK) & ~0x1; opdata = *((int *)((char *) base + offset)); op = SPE_C99_OP(opdata); if ((op <= 0) || (op >= SPE_C99_NR_OPCODES)) { DEBUG_PRINTF("%s: Unhandled type %08x\n", __func__, SPE_C99_OP(opdata)); return 1; } default_c99_funcs[op] ((char *) base, opdata); return 0; } libspe2-2.2.80-95/spebase/load.c0000644000175100017510000001424010673437510015510 0ustar arthurarthur/* * libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include "elf_loader.h" #include "create.h" #include "spebase.h" #ifndef SPE_EMULATED_LOADER_FILE #define SPE_EMULATED_LOADER_FILE "/usr/lib/spe/emulated-loader.bin" #endif /** * Register the SPE program's start address with the oprofile and gdb, by * writing to the object-id file. */ void _base_spe_program_load_complete(spe_context_ptr_t spectx) { 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(); } /** * Send the isolated app loading parameters to the SPE. * * Helper function for internal libspe use. * * @param spe The SPE thread to send the mailbox message to * @param addr_h The high 32-bits of the address of the isolated app * @param addr_l The low 32-bits of the address of the isolated app * @param size The size of the isolated app binary * @return zero on success, non-zero on failure */ static inline int __write_isolated_load_params(struct spe_context *spe, uint32_t addr_h, uint32_t addr_l, uint32_t size) { int fd = _base_spe_open_if_closed(spe, FD_WBOX, 0); if (fd < 0) { DEBUG_PRINTF("%s: can't open wbox\n", __FUNCTION__); return -1; } if ((write(fd, &addr_h, sizeof(uint32_t)) != sizeof(uint32_t)) || (write(fd, &addr_l, sizeof(uint32_t)) != sizeof(uint32_t)) || (write(fd, &size, sizeof(uint32_t)) != sizeof(uint32_t))) { DEBUG_PRINTF("%s: error writing to wbox\n", __FUNCTION__); return -1; } return 0; } /** * Initiate transfer of an isolated SPE app by the loader kernel. * * Helper function for internal libspe use. * * @param thread The SPE thread to load the app to * @param handle The handle to the spe program * @return zero on success, non-zero on failure; */ static int spe_start_isolated_app(struct spe_context *spe, spe_program_handle_t *handle) { uint64_t addr; uint32_t size, addr_h, addr_l; if (_base_spe_parse_isolated_elf(handle, &addr, &size)) { DEBUG_PRINTF("%s: invalid isolated image\n", __FUNCTION__); errno = ENOEXEC; return -errno; } if (addr & 0xf) { DEBUG_PRINTF("%s: isolated image is incorrectly aligned\n", __FUNCTION__); errno = EINVAL; return -errno; } addr_l = (uint32_t)(addr & 0xffffffff); addr_h = (uint32_t)(addr >> 32); DEBUG_PRINTF("%s: Sending isolated app params: 0x%08x 0x%08x 0x%08x\n", __FUNCTION__, addr_h, addr_l, size); if (__write_isolated_load_params(spe, addr_h, addr_l, size)) { errno = EIO; return -errno; } return 0; } /** * Load the emulated isolation loader program from the filesystem * * @return The loader program, or NULL if it can't be loaded. The loader binary * is cached between calls. */ static spe_program_handle_t *emulated_loader_program(void) { static spe_program_handle_t *loader = NULL; if (!loader) loader = _base_spe_image_open(SPE_EMULATED_LOADER_FILE); if (!loader) DEBUG_PRINTF("Can't load emulated loader '%s': %s\n", SPE_EMULATED_LOADER_FILE, strerror(errno)); return loader; } /** * Check if the emulated loader is present in the filesystem * @return Non-zero if the loader is available, otherwise zero. */ int _base_spe_emulated_loader_present(void) { spe_program_handle_t *loader = emulated_loader_program(); if (!loader) return 0; return !_base_spe_verify_spe_elf_image(loader); } /** * Initiate transfer of an emulated isolated SPE app by the loader kernel. * * Helper function for internal libspe use. * * @param thread The SPE thread to load the app to * @param handle The handle to the (isolated) spe program * @param ld_info[out] Loader information about the entry point of the SPE. * This will reference the loader, not the SPE program, as * we will be running the loader first. * @return zero on success, non-zero on failure; */ static int spe_start_emulated_isolated_app(struct spe_context *spe, spe_program_handle_t *handle, struct spe_ld_info *ld_info) { int rc; spe_program_handle_t *loader; /* load emulated loader from the filesystem */ loader = emulated_loader_program(); if (!loader) return -1; rc = _base_spe_load_spe_elf(loader, spe->base_private->mem_mmap_base, ld_info); if (rc != 0) { DEBUG_PRINTF("%s: No loader available\n", __FUNCTION__); return rc; } return spe_start_isolated_app(spe, handle); } int _base_spe_program_load(spe_context_ptr_t spe, spe_program_handle_t *program) { 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; } libspe2-2.2.80-95/spebase/default_libea_handler.h0000644000175100017510000000106210650126374021047 0ustar arthurarthur #define SPE_LIBEA_CLASS 0x2105 #define SPE_LIBEA_UNUSED 0x00 #define SPE_LIBEA_CALLOC 0x01 #define SPE_LIBEA_FREE 0x02 #define SPE_LIBEA_MALLOC 0x03 #define SPE_LIBEA_REALLOC 0x04 #define SPE_LIBEA_NR_OPCODES 0x05 extern int _base_spe_default_libea_handler(char *ls, unsigned long args); #define SPE_LIBEA_OP_SHIFT 24 #define SPE_LIBEA_OP_MASK 0xff #define SPE_LIBEA_DATA_MASK 0xffffff #define SPE_LIBEA_OP(_v) (((_v) >> SPE_LIBEA_OP_SHIFT) & SPE_LIBEA_OP_MASK) #define SPE_LIBEA_DATA(_v) ((_v) & SPE_LIBEA_DATA_MASK) libspe2-2.2.80-95/spebase/image.c0000644000175100017510000000537310650125723015655 0ustar arthurarthur/* * libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include "elf_loader.h" #include "spebase.h" struct image_handle { spe_program_handle_t speh; unsigned int map_size; }; spe_program_handle_t *_base_spe_image_open(const char *filename) { /* 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; } int _base_spe_image_close(spe_program_handle_t *handle) { 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; } libspe2-2.2.80-95/spebase/Makefile0000644000175100017510000000407110642220342016053 0ustar arthurarthur#* #* libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS #* Copyright (C) 2005 IBM Corp. #* #* This library is free software; you can redistribute it and/or modify it #* under the terms of the GNU Lesser General Public License as published by #* the Free Software Foundation; either version 2.1 of the License, #* or (at your option) any later version. #* #* This library is distributed in the hope that it will be useful, but #* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY #* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public #* License for more details. #* #* You should have received a copy of the GNU Lesser General Public License #* along with this library; if not, write to the Free Software Foundation, #* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #* TOP=.. include $(TOP)/make.defines MAJOR_VERSION := 2 MINOR_VERSION := 0.0 EMULATED_LOADER := $(libdir)/spe/emulated-loader.bin libspebase_A := libspebase.a libspebase_SO := libspebase.so.${MAJOR_VERSION}.${MINOR_VERSION} libspebase_SONAME := libspebase.so.${MAJOR_VERSION} libspebase_OBJS := create.o elf_loader.o load.o run.o image.o lib_builtin.o \ default_c99_handler.o default_posix1_handler.o default_libea_handler.o \ dma.o mbox.o accessors.o info.o CFLAGS += -I.. CFLAGS += -D_ATFILE_SOURCE load.o: CPPFLAGS+='-DSPE_EMULATED_LOADER_FILE="$(EMULATED_LOADER)"' all: $(libspebase_SO) $(libspebase_A) install-so: $(libspebase_SO) $(libspebase_A) $(INSTALL_DIR) $(ROOT)$(includedir) $(INSTALL_DATA) spebase.h $(ROOT)$(includedir)/spebase.h $(INSTALL_DATA) cbea_map.h $(ROOT)$(includedir)/cbea_map.h $(INSTALL_DIR) $(ROOT)$(speinclude) $(INSTALL_DATA) cbea_map.h $(ROOT)$(speinclude)/cbea_map.h clean: rm -rf $(libspebase_A) $(libspebase_OBJS) $(libspebase_SO) $(libspebase_SO): $(libspebase_OBJS) $(CC) $(CFLAGS) -shared -o $@ $^ -lrt -lpthread -Wl,--soname=${libspebase_SONAME} $(libspebase_A): $(libspebase_OBJS) $(CROSS)ar -r $(libspebase_A) $(libspebase_OBJS) libspe2-2.2.80-95/spebase/lib_builtin.h0000644000175100017510000000211210650126050017052 0ustar arthurarthur/* * libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _lib_buildin_h_ #define _lib_buildin_h_ #include "spebase.h" #define MAX_CALLNUM 255 #define RESERVED 4 extern int _base_spe_handle_library_callback(struct spe_context *spe, int callnum, unsigned int npc); #endif libspe2-2.2.80-95/spebase/spebase.h0000644000175100017510000006244210660561303016221 0ustar arthurarthur/* * libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /** \file * spebase.h contains the public API funtions */ #ifndef _spebase_h_ #define _spebase_h_ #ifdef __cplusplus extern "C" { #endif #include #include "libspe2-types.h" #define __PRINTF(fmt, args...) { fprintf(stderr,fmt , ## args); } #ifdef DEBUG #define DEBUG_PRINTF(fmt, args...) __PRINTF(fmt , ## args) #else #define DEBUG_PRINTF(fmt, args...) #endif /** NOTE: NUM_MBOX_FDS must always be the last element in the enumeration */ 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 }; /* * "Private" structure -- do no use, if you want to achieve binary compatibility */ struct spe_context_base_priv { /* mutex to protect members which modified in lifetime of the context: spe_fds_array, entry */ pthread_mutex_t fd_lock[NUM_MBOX_FDS]; /* SPE Group base directory fd */ int fd_grp_dir; /* SPE SPUFS base dir fd*/ int fd_spe_dir; /* SPE Program execution and environment flags */ unsigned int flags; /* SPE Mailbox and Signal fds */ int spe_fds_array[NUM_MBOX_FDS]; int spe_fds_refcount[NUM_MBOX_FDS]; /* event pipes for speevent library */ int ev_pipe[2]; /* Base Addresses of memory mapped SPE areas */ void *psmap_mmap_base; void *mem_mmap_base; void *mfc_mmap_base; void *mssync_mmap_base; void *cntl_mmap_base; void *signal1_mmap_base; void *signal2_mmap_base; /* SPE program entry point generated by elf_load() */ int entry; /* pointer to the program loaded/being loaded to the SPE. We need to * store this to allow deferred updates to gdb, when loading is * asynchronous (ie, isolated load, which is performed by the SPE). */ spe_program_handle_t *loaded_program; /* We need to keep the entry point for emulated isolated contexts, * and ignore the value provided to spe_context_run */ int emulated_entry; /* This is used to keep track of tags used for proxy DMA operations * so we can use the zero tagmask parameter in the status functions*/ int active_tagmask; }; /* spe related sizes */ #define LS_SIZE 0x40000 /* 256K (in bytes) */ #define PSMAP_SIZE 0x20000 /* 128K (in bytes) */ #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 /** * Location of the PPE-assisted library call buffer * for emulated isolation contexts. */ #define SPE_EMULATE_PARAM_BUFFER 0x3e000 /* */ #define SPE_PROGRAM_NORMAL_END 0x2000 #define SPE_PROGRAM_LIBRARY_CALL 0x2100 /** * Isolated exit codes: 0x220x */ #define SPE_PROGRAM_ISOLATED_STOP 0x2200 #define SPE_PROGRAM_ISO_LOAD_COMPLETE 0x2206 /** * spe_context: This holds the persistant information of a SPU instance * it is created by spe_create_context() */ struct spe_gang_context_base_priv { /* SPE Gang execution and environment flags */ unsigned int flags; /* SPE Mailbox and Signal fds */ int fd_gang_dir; char gangname[256]; }; /* Function Prototypes */ /** * _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) * * @param flags * @param gctx specify NULL if not belonging to a gang * @param aff_spe specify NULL to skip affinity information */ extern spe_context_ptr_t _base_spe_context_create(unsigned int flags, spe_gang_context_ptr_t gctx, spe_context_ptr_t aff_spe); /** * 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) */ extern spe_gang_context_ptr_t _base_spe_gang_context_create(unsigned int flags); /** * _base_spe_program_load loads an ELF image into a context * * @param spectx Specifies the SPE context * * @param program handle to the ELF image */ extern int _base_spe_program_load(spe_context_ptr_t spectx, spe_program_handle_t *program); /** * 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 * * @pre spe->base_priv->loaded_program is a valid SPE program * @param spectx The spe context that has been loaded. */ void _base_spe_program_load_complete(spe_context_ptr_t spectx); /** * Check if the emulated loader is present in the filesystem * @return Non-zero if the loader is available, otherwise zero. */ int _base_spe_emulated_loader_present(void); /** * _base_spe_context_destroy cleans up what is left when an SPE executable has exited. * Closes open file handles and unmaps memory areas. * * @param spectx Specifies the SPE context */ extern int _base_spe_context_destroy(spe_context_ptr_t spectx); /** * _base_spe_gang_context_destroy destroys a gang context and frees associated resources * * @param gctx Specifies the SPE gang context */ extern int _base_spe_gang_context_destroy(spe_gang_context_ptr_t gctx); /** * _base_spe_context_run starts execution of an SPE context with a loaded image * * @param spectx Specifies the SPE context * * @param entry entry point for the SPE programm. If set to 0, entry point is determined * by the ELF loader. * * @param runflags valid values are:\n * SPE_RUN_USER_REGS Specifies that the SPE setup registers r3, r4, and r5 are initialized * with the 48 bytes pointed to by argp.\n * SPE_NO_CALLBACKS do not use built in library functions.\n * * * @param argp An (optional) pointer to application specific data, and is passed as the second * parameter to the SPE program. * * @param envp An (optional) pointer to environment specific data, and is passed as the third * parameter to the SPE program. */ extern 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_image_close unmaps an SPE ELF object that was previously mapped using * spe_open_image. * @param handle handle to open file * * @retval 0 On success, spe_close_image 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_open_image. */ 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 * 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. * * @param filename Specifies the filename of an SPE ELF executable to be loaded * and mapped into system memory. * * @return 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.\n * Possible values for errno include:\n * EACCES The calling process does not have permission to access the * specified file.\n * 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. * @sa spe_create_thread */ extern spe_program_handle_t *_base_spe_image_open(const char *filename); /** * 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. * * @param spectx Specifies the SPE context * @param ls Specifies the starting local store destination address. * @param ea Specifies the starting effective address source address. * @param size Specifies the size, in bytes, to be transferred. * @param tag Specifies the tag id used to identify the DMA command. * @param tid Specifies the transfer class identifier of the DMA command. * @param rid Specifies the replacement class identifier of the DMA command. * @return On success, return 0. On failure, -1 is returned. */ extern 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_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. * * @param spectx Specifies the SPE context * @param ls Specifies the starting local store destination address. * @param ea Specifies the starting effective address source address. * @param size Specifies the size, in bytes, to be transferred. * @param tag Specifies the tag id used to identify the DMA command. * @param tid Specifies the transfer class identifier of the DMA command. * @param rid Specifies the replacement class identifier of the DMA command. * @return On success, return 0. On failure, -1 is returned. */ 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_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. * * @param spectx Specifies the SPE context * @param ls Specifies the starting local store destination address. * @param ea Specifies the starting effective address source address. * @param size Specifies the size, in bytes, to be transferred. * @param tag Specifies the tag id used to identify the DMA command. * @param tid Specifies the transfer class identifier of the DMA command. * @param rid Specifies the replacement class identifier of the DMA command. * @return On success, return 0. On failure, -1 is returned. */ 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_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. * @param spectx Specifies the SPE context * @param ls Specifies the starting local store destination address. * @param ea Specifies the starting effective address source address. * @param size Specifies the size, in bytes, to be transferred. * @param tag Specifies the tag id used to identify the DMA command. * @param tid Specifies the transfer class identifier of the DMA command. * @param rid Specifies the replacement class identifier of the DMA command. * @return On success, return 0. On failure, -1 is returned. */ 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_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. * * @param spectx Specifies the SPE context * @param ls Specifies the starting local store destination address. * @param ea Specifies the starting effective address source address. * @param size Specifies the size, in bytes, to be transferred. * @param tag Specifies the tag id used to identify the DMA command. * @param tid Specifies the transfer class identifier of the DMA command. * @param rid Specifies the replacement class identifier of the DMA command. * @return On success, return 0. On failure, -1 is returned. */ 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_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. * * @param spectx Specifies the SPE context * @param ls Specifies the starting local store destination address. * @param ea Specifies the starting effective address source address. * @param size Specifies the size, in bytes, to be transferred. * @param tag Specifies the tag id used to identify the DMA command. * @param tid Specifies the transfer class identifier of the DMA command. * @param rid Specifies the replacement class identifier of the DMA command. * @return On success, return 0. On failure, -1 is returned. */ 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_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. * * @param spectx Specifies the SPE thread whose outbound mailbox is to be read. * @param mbox_data * @param count * * * @retval >0 the number of 32-bit mailbox messages read * @retval =0 no data available * @retval -1 error condition and errno is set\n * Possible values for errno:\n * EINVAL speid is invalid\n * Exxxx what else do we need here?? */ int _base_spe_out_mbox_read(spe_context_ptr_t spectx, unsigned int mbox_data[], int count); /** * 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. * * @param spectx Specifies the SPE thread whose outbound mailbox is to be read. * @param mbox_data * @param count * @param behavior_flag * ALL_BLOCKING\n * ANY_BLOCKING\n * ANY_NON_BLOCKING\n * * @retval >=0 the number of 32-bit mailbox messages written * @retval -1 error condition and errno is set\n * Possible values for errno:\n * EINVAL spectx is invalid\n * Exxxx what else do we need here?? */ 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_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. * * @param spectx Specifies the SPE context whose mailbox status is to be read. * @return On success, returns the current status of the mailbox, respectively. * On failure, -1 is returned. * @sa spe_read_out_mbox, spe_write_in_mbox, read (2) */ int _base_spe_in_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. * * @param spectx Specifies the SPE context whose mailbox status is to be read. * @return On success, returns the current status of the mailbox, respectively. * On failure, -1 is returned. * @sa spe_read_out_mbox, spe_write_in_mbox, read (2) */ int _base_spe_out_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. * * @param spectx Specifies the SPE context whose mailbox status is to be read. * @return On success, returns the current status of the mailbox, respectively. * On failure, -1 is returned. * @sa spe_read_out_mbox, spe_write_in_mbox, read (2) */ int _base_spe_out_intr_mbox_status(spe_context_ptr_t spectx); /** * The _base_spe_out_intr_mbox_read function reads the contents of the SPE outbound interrupting * mailbox for the SPE context. */ int _base_spe_out_intr_mbox_read(spe_context_ptr_t spectx, unsigned int mbox_data[], int count, int behavior_flag); /** * 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. * * @param spectx Specifies the SPE context whose signal register is to be written to. * @param signal_reg Specified the signal notification register to be written. * Valid signal notification registers are:\n * SPE_SIG_NOTIFY_REG_1 SPE signal notification register 1\n * SPE_SIG_NOTIFY_REG_2 SPE signal notification register 2\n * @param data The 32-bit data to be written to the specified signal notification * register. * @return On success, spe_write_signal returns 0. On failure, -1 is returned. * @sa spe_get_ps_area, spe_write_in_mbox */ int _base_spe_signal_write(spe_context_ptr_t spectx, unsigned int signal_reg, unsigned int data ); /** * register a handler function for the specified number * NOTE: registering a handler to call zero and one is ignored. */ extern int _base_spe_callback_handler_register(void * handler, unsigned int callnum, unsigned int mode); /** * unregister a handler function for the specified number * NOTE: unregistering a handler from call zero and one is ignored. */ extern int _base_spe_callback_handler_deregister(unsigned int callnum ); /** * query a handler function for the specified number */ extern void * _base_spe_callback_handler_query(unsigned int callnum ); /** * _base_spe_stop_reason_get * * @param spectx one thread for which to check why it was stopped * * @retval 0 success - eventid and eventdata set appropriately * @retval 1 spe has not stopped after checking last, so no data was written * to event * @retval -1 an error has happened, event was not touched, errno gets set\n * Possible vales for errno:\n * EINVAL speid is invalid\n * Exxxx what else do we need here?? */ int _base_spe_stop_reason_get(spe_context_ptr_t spectx); /** * _base_spe_mfcio_tag_status_read * * No Idea * */ int _base_spe_mfcio_tag_status_read(spe_context_ptr_t spectx, unsigned int mask, unsigned int behavior, unsigned int *tag_status); /** * __base_spe_stop_event_source_get * * @param spectx Specifies the SPE context */ int __base_spe_stop_event_source_get(spe_context_ptr_t spectx); /** * __base_spe_stop_event_target_get * * @param spectx Specifies the SPE context */ int __base_spe_stop_event_target_get(spe_context_ptr_t spectx); /** * _base_spe_stop_status_get * * @param spectx Specifies the SPE context * */ int _base_spe_stop_status_get(spe_context_ptr_t spectx); /** * __base_spe_event_source_acquire opens a file descriptor to the specified event source * * @param spectx Specifies the SPE context * * @param fdesc Specifies the event source */ int __base_spe_event_source_acquire(struct spe_context *spectx, enum fd_name fdesc); /** * __base_spe_event_source_release releases the file descriptor to the specified event source * * @param spectx Specifies the SPE context * * @param fdesc Specifies the event source */ void __base_spe_event_source_release(struct spe_context *spectx, enum fd_name fdesc); /** * _base_spe_ps_area_get returns a pointer to the start of memory mapped problem state * area * * @param spectx Specifies the SPE context * * @param area specifes the area to map */ void* _base_spe_ps_area_get(struct spe_context *spectx, enum ps_area area); /** * __base_spe_spe_dir_get return the file descriptor of the SPE directory in spufs * * @param spectx Specifies the SPE context */ int __base_spe_spe_dir_get(struct spe_context *spectx); /** * _base_spe_ls_area_get returns a pointer to the start of the memory mapped * local store area * * @param spectx Specifies the SPE context */ void* _base_spe_ls_area_get(struct spe_context *spectx); /** * _base_spe_ls_size_get returns the size of the local store area * * @param spectx Specifies the SPE context */ int _base_spe_ls_size_get(spe_context_ptr_t spe); /** * _base_spe_context_lock locks members of the SPE context * * @param spectx Specifies the SPE context * @param fd Specifies the file */ void _base_spe_context_lock(spe_context_ptr_t spe, enum fd_name fd); /** * _base_spe_context_unlock unlocks members of the SPE context * * @param spectx Specifies the SPE context * @param fd Specifies the file */ void _base_spe_context_unlock(spe_context_ptr_t spe, enum fd_name fd); /** * _base_spe_info_get */ int _base_spe_cpu_info_get(int info_requested, int cpu_node); /** * __spe_context_update_event internal function for gdb notification. * */ void __spe_context_update_event(void); /** * _base_spe_mssync_start starts Multisource Synchronisation * * @param spectx Specifies the SPE context */ int _base_spe_mssync_start(spe_context_ptr_t spectx); /** * _base_spe_mssync_status retrieves status of Multisource Synchronisation * * @param spectx Specifies the SPE context */ int _base_spe_mssync_status(spe_context_ptr_t spectx); #ifdef __cplusplus } #endif #endif libspe2-2.2.80-95/spebase/info.c0000644000175100017510000000571310627520105015521 0ustar arthurarthur/* * libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include "info.h" /* * For the moment, we count the numbers of cpus and devide by 2. */ int _base_spe_count_physical_cpus(int cpu_node) { const char *buff = "/sys/devices/system/cpu"; DIR *dirp; int ret = -2; struct dirent *dptr; DEBUG_PRINTF ("spe_count_physical_cpus()\n"); // make sure, cpu_node is in the correct range if (cpu_node != -1) { errno = EINVAL; return -1; } // Count number of CPUs in /sys/devices/system/cpu if((dirp=opendir(buff))==NULL) { fprintf(stderr,"Error opening %s ",buff); perror("dirlist"); errno = EINVAL; return -1; } while((dptr=readdir(dirp))) { ret++; } closedir(dirp); return ret/THREADS_PER_BE; } /* * For the moment, we use all spes which are controlled by linux */ int _base_spe_count_usable_spes(int cpu_node) { return _base_spe_count_physical_spes(cpu_node); // FIXME } /* * For the moment, we assume all SPEs are evenly distributed over the * physical cpsus. */ int _base_spe_count_physical_spes(int cpu_node) { const char *buff = "/sys/devices/system/spu"; DIR *dirp; int ret = -2; struct dirent *dptr; int no_of_bes; DEBUG_PRINTF ("spe_count_physical_spes()\n"); // make sure, cpu_node is in the correct range no_of_bes = _base_spe_count_physical_cpus(-1); if (cpu_node < -1 || cpu_node >= no_of_bes ) { errno = EINVAL; return -1; } // Count number of SPUs in /sys/devices/system/spu if((dirp=opendir(buff))==NULL) { fprintf(stderr,"Error opening %s ",buff); perror("dirlist"); errno = EINVAL; return -1; } while((dptr=readdir(dirp))) { ret++; } closedir(dirp); if(cpu_node != -1) ret /= no_of_bes; // FIXME return ret; } int _base_spe_cpu_info_get(int info_requested, int cpu_node) { 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; } libspe2-2.2.80-95/spebase/dma.c0000644000175100017510000002520510654073561015336 0ustar arthurarthur/* * libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include "create.h" #include "dma.h" static int spe_read_tag_status_block(spe_context_ptr_t spectx, unsigned int mask, unsigned int *tag_status); static int spe_read_tag_status_noblock(spe_context_ptr_t spectx, unsigned int mask, unsigned int *tag_status); static int issue_mfc_command(spe_context_ptr_t spectx, unsigned lsa, void *ea, unsigned size, unsigned tag, unsigned tid, unsigned rid, enum mfc_cmd cmd) { int ret; DEBUG_PRINTF("queuing DMA %x %lx %x %x %x %x %x\n", lsa, (unsigned long)ea, size, tag, tid, rid, (unsigned)cmd); /* tag 16-31 are reserved by kernel */ if (tag > 0x0f || tid > 0xff || rid > 0xff) { errno = EINVAL; return -1; } if (spectx->base_private->flags & SPE_MAP_PS) { volatile struct spe_mfc_command_area *cmd_area = spectx->base_private->mfc_mmap_base; unsigned int eal = (uintptr_t) ea & 0xFFFFFFFF; unsigned int eah = (unsigned long long)(uintptr_t) ea >> 32; _base_spe_context_lock(spectx, FD_MFC); spectx->base_private->active_tagmask |= 1 << tag; DEBUG_PRINTF("set active tagmask = 0x%04x, tag=%i\n",spectx->base_private->active_tagmask,tag); while ((cmd_area->MFC_QStatus & 0x0000FFFF) == 0) ; do { cmd_area->MFC_LSA = lsa; cmd_area->MFC_EAH = eah; cmd_area->MFC_EAL = eal; cmd_area->MFC_Size_Tag = (size << 16) | tag; cmd_area->MFC_ClassID_CMD = (tid << 24) | (rid << 16) | cmd; ret = cmd_area->MFC_CMDStatus & 0x00000003; } while (ret); // at least one of the two bits is set _base_spe_context_unlock(spectx, FD_MFC); return 0; } else { int fd; fd = _base_spe_open_if_closed(spectx, FD_MFC, 0); if (fd != -1) { struct mfc_command_parameter_area parm = { .lsa = lsa, .ea = (unsigned long) ea, .size = size, .tag = tag, .class = (tid << 8) | rid, .cmd = cmd, }; ret = write(fd, &parm, sizeof (parm)); if ((ret < 0) && (errno != EIO)) { perror("spe_do_mfc_put: internal error"); } return ret < 0 ? -1 : 0; } } /* the kernel does not support DMA */ return 1; } static int spe_do_mfc_put(spe_context_ptr_t spectx, unsigned src, void *dst, unsigned size, unsigned tag, unsigned tid, unsigned rid, enum mfc_cmd cmd) { int ret; ret = issue_mfc_command(spectx, src, dst, size, tag, tid, rid, cmd); if (ret <= 0) { return ret; } else { /* the kernel does not support DMA, so just copy directly */ memcpy(dst, spectx->base_private->mem_mmap_base + src, size); return 0; } } static int spe_do_mfc_get(spe_context_ptr_t spectx, unsigned int dst, void *src, unsigned int size, unsigned int tag, unsigned tid, unsigned rid, enum mfc_cmd cmd) { int ret; ret = issue_mfc_command(spectx, dst, src, size, tag, tid, rid, cmd); if (ret <= 0) { return ret; } else { /* the kernel does not support DMA, so just copy directly */ memcpy(spectx->base_private->mem_mmap_base + dst, src, size); return 0; } } 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) { 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) { 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) { return spe_do_mfc_put(spectx, ls, ea, size, tag, tid, rid, MFC_CMD_PUTF); } 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) { 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) { 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) { return spe_do_mfc_get(spectx, ls, ea, size, tag, tid, rid, MFC_CMD_GETF); } static int spe_mfcio_tag_status_read_all(spe_context_ptr_t spectx, unsigned int mask, unsigned int *tag_status) { int fd; if (spectx->base_private->flags & SPE_MAP_PS) { return spe_read_tag_status_block(spectx, mask, tag_status); } else { fd = _base_spe_open_if_closed(spectx, FD_MFC, 0); if (fd == -1) { return -1; } if (fsync(fd) != 0) { return -1; } return spe_read_tag_status_block(spectx, mask, tag_status); } } static int spe_mfcio_tag_status_read_any(spe_context_ptr_t spectx, unsigned int mask, unsigned int *tag_status) { return spe_read_tag_status_block(spectx, mask, tag_status); } static int spe_mfcio_tag_status_read_immediate(spe_context_ptr_t spectx, unsigned int mask, unsigned int *tag_status) { return spe_read_tag_status_noblock(spectx, mask, tag_status); } /* MFC Read tag status functions * */ static int spe_read_tag_status_block(spe_context_ptr_t spectx, unsigned int mask, unsigned int *tag_status) { if (spectx->base_private->flags & SPE_MAP_PS) { volatile struct spe_mfc_command_area *cmd_area = spectx->base_private->mfc_mmap_base; _base_spe_context_lock(spectx, FD_MFC); cmd_area->Prxy_QueryMask = mask; __asm__ ("eieio"); do { *tag_status = cmd_area->Prxy_TagStatus; spectx->base_private->active_tagmask ^= *tag_status; DEBUG_PRINTF("unset active tagmask = 0x%04x, tag_status = 0x%04x\n", spectx->base_private->active_tagmask,*tag_status); } while (*tag_status ^ mask); _base_spe_context_unlock(spectx, FD_MFC); return 0; } else { int fd; fd = _base_spe_open_if_closed(spectx, FD_MFC, 0); if (fd == -1) { return -1; } if (read(fd,tag_status,4) == 4) { return 0; } } return -1; } static int spe_read_tag_status_noblock(spe_context_ptr_t spectx, unsigned int mask, unsigned int *tag_status) { unsigned int ret; if (spectx->base_private->flags & SPE_MAP_PS) { volatile struct spe_mfc_command_area *cmd_area = spectx->base_private->mfc_mmap_base; _base_spe_context_lock(spectx, FD_MFC); cmd_area->Prxy_QueryMask = mask; __asm__ ("eieio"); *tag_status = cmd_area->Prxy_TagStatus; spectx->base_private->active_tagmask ^= *tag_status; DEBUG_PRINTF("unset active tagmask = 0x%04x, tag_status = 0x%04x\n", spectx->base_private->active_tagmask,*tag_status); _base_spe_context_unlock(spectx, FD_MFC); return 0; } else { struct pollfd poll_fd; int fd; fd = _base_spe_open_if_closed(spectx, FD_MFC, 0); if (fd == -1) { return -1; } poll_fd.fd = fd; poll_fd.events = POLLIN; ret = poll(&poll_fd, 1, 0); if (ret < 0) return -1; if (ret == 0 || !(poll_fd.revents & POLLIN)) { *tag_status = 0; return 0; } if (read(fd,tag_status,4) == 4) { return 0; } } return -1; } int _base_spe_mfcio_tag_status_read(spe_context_ptr_t spectx, unsigned int mask, unsigned int behavior, unsigned int *tag_status) { 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) { 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; } } int _base_spe_mssync_status(spe_context_ptr_t spectx) { 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; } } libspe2-2.2.80-95/spebase/default_c99_handler.h0000644000175100017510000000205210650126163020373 0ustar arthurarthur/* default_c99_handler.h - emulate SPE C99 library calls. * * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __DEFAULT_C99_HANDLER_H__ #define __DEFAULT_C99_HANDLER_H__ #define SPE_C99_CLASS 0x2100 extern int _base_spe_default_c99_handler(unsigned long *base, unsigned long args); #endif /* __DEFAULT_C99_HANDLER_H__ */ libspe2-2.2.80-95/spebase/mbox.h0000644000175100017510000000162210600243027015527 0ustar arthurarthur/* * libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _mbox_h_ #define _mbox_h_ #include "spebase.h" #endif libspe2-2.2.80-95/spebase/elf_loader.c0000644000175100017510000002445610650125723016672 0ustar arthurarthur/* * libspe2 - A wrapper to allow direct execution of SPE binaries * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include "elf_loader.h" #include "spebase.h" #ifdef DEBUG static void display_debug_output(Elf32_Ehdr *elf_start, Elf32_Shdr *sh); #endif /*DEBUG*/ #define __PRINTF(fmt, args...) { fprintf(stderr,fmt , ## args); } #ifdef DEBUG #define DEBUG_PRINTF(fmt, args...) __PRINTF(fmt , ## args) #define TAG DEBUG_PRINTF("TAG: %d@%s\n", __LINE__, __FILE__); #else #define DEBUG_PRINTF(fmt, args...) #define TAG #endif static const unsigned char expected[EI_PAD] = { [EI_MAG0] = ELFMAG0, [EI_MAG1] = ELFMAG1, [EI_MAG2] = ELFMAG2, [EI_MAG3] = ELFMAG3, [EI_CLASS] = ELFCLASS32, [EI_DATA] = ELFDATA2MSB, [EI_VERSION] = EV_CURRENT, [EI_OSABI] = ELFOSABI_SYSV, [EI_ABIVERSION] = 0 }; static int check_spe_elf(Elf32_Ehdr *ehdr) { /* Validate ELF */ if (memcmp (ehdr->e_ident, expected, EI_PAD) != 0) { DEBUG_PRINTF ("invalid ELF header.\n"); DEBUG_PRINTF ("expected 0x%016llX != 0x%016llX\n", *(long long *) expected, *(long long *) (ehdr->e_ident)); errno = EINVAL; return -errno; } /* Validate the machine type */ if (ehdr->e_machine != 0x17) { DEBUG_PRINTF ("not an SPE ELF object"); errno = EINVAL; return -errno; } /* Validate ELF object type. */ if (ehdr->e_type != ET_EXEC) { DEBUG_PRINTF ("invalid SPE ELF type.\n"); DEBUG_PRINTF ("SPE type %d != %d\n", ehdr->e_type, ET_EXEC); errno = EINVAL; DEBUG_PRINTF ("parse_spu_elf(): errno=%d.\n", errno); return -errno; } return 0; } /** * verifies integrity of an SPE image */ int _base_spe_verify_spe_elf_image(spe_program_handle_t *handle) { Elf32_Ehdr *ehdr; void *elf_start; elf_start = handle->elf_image; ehdr = (Elf32_Ehdr *)(handle->elf_image); return check_spe_elf(ehdr); } int _base_spe_parse_isolated_elf(spe_program_handle_t *handle, uint64_t *addr, uint32_t *size) { Elf32_Ehdr *ehdr = (Elf32_Ehdr *)handle->elf_image; Elf32_Phdr *phdr; if (!ehdr) { DEBUG_PRINTF("No ELF image has been loaded\n"); errno = EINVAL; return -errno; } if (ehdr->e_phentsize != sizeof(*phdr)) { DEBUG_PRINTF("Invalid program header format (phdr size=%d)\n", ehdr->e_phentsize); errno = EINVAL; return -errno; } if (ehdr->e_phnum != 1) { DEBUG_PRINTF("Invalid program header count (%d), expected 1\n", ehdr->e_phnum); errno = EINVAL; return -errno; } phdr = (Elf32_Phdr *)(handle->elf_image + ehdr->e_phoff); if (phdr->p_type != PT_LOAD || phdr->p_memsz == 0) { DEBUG_PRINTF("SPE program segment is not loadable (type=%x)\n", phdr->p_type); errno = EINVAL; return -errno; } if (addr) *addr = (uint64_t)(unsigned long) (handle->elf_image + phdr->p_offset); if (size) *size = phdr->p_memsz; return 0; } static int overlay(Elf32_Phdr *ph, Elf32_Phdr *prev_ph) { /* * If our ph segment virtual address fits within that of the * previous ph, this is an overlay. */ if (prev_ph && (ph->p_vaddr >= prev_ph->p_vaddr) && (ph->p_vaddr < (prev_ph->p_vaddr + prev_ph->p_memsz))) return 1; else return 0; } static void copy_to_ld_buffer(spe_program_handle_t *handle, void *buffer, Elf32_Phdr *ph, Elf32_Off toe_addr, long toe_size) { void *start = handle->elf_image; DEBUG_PRINTF("SPE_LOAD %p (0x%x) -> %p (0x%x) (%i bytes)\n", buffer + ph->p_vaddr, ph->p_vaddr, start + ph->p_offset, ph->p_offset, ph->p_filesz); /* toe segment comes from the shadow */ if (ph->p_vaddr == toe_addr) { /* still makes a copy if toe is buried with other * sections */ if (toe_size != ph->p_filesz && ph->p_filesz) { DEBUG_PRINTF("loading base copy\n"); memcpy(buffer + ph->p_vaddr, start + ph->p_offset, ph->p_filesz); } /* overlay only the total toe section size */ DEBUG_PRINTF("loading toe %X %X\n", ph->p_offset, toe_addr); memcpy(buffer + ph->p_vaddr, handle->toe_shadow, toe_size); } else if (ph->p_filesz) { memcpy(buffer + ph->p_vaddr, start + ph->p_offset, ph->p_filesz); } DEBUG_PRINTF("done ...\n"); } int _base_spe_load_spe_elf (spe_program_handle_t *handle, void *ld_buffer, struct spe_ld_info *ld_info) { Elf32_Ehdr *ehdr; Elf32_Phdr *phdr; Elf32_Phdr *ph, *prev_ph; Elf32_Shdr *shdr; Elf32_Shdr *sh; Elf32_Off toe_addr = 0; long toe_size = 0; char* str_table = 0; int num_load_seg = 0; void *elf_start; int ret; DEBUG_PRINTF ("load_spe_elf(%p, %p)\n", handle, ld_buffer); elf_start = handle->elf_image; DEBUG_PRINTF ("load_spe_elf(%p, %p)\n", handle->elf_image, ld_buffer); ehdr = (Elf32_Ehdr *)(handle->elf_image); /* Check for a Valid SPE ELF Image (again) */ if ((ret=check_spe_elf(ehdr))) return ret; /* Start processing headers */ phdr = (Elf32_Phdr *) ((char *) ehdr + ehdr->e_phoff); shdr = (Elf32_Shdr *) ((char *) ehdr + ehdr->e_shoff); str_table = (char*)ehdr + shdr[ehdr->e_shstrndx].sh_offset; /* traverse the sections to locate the toe segment */ /* by specification, the toe sections are grouped together in a segment */ for (sh = shdr; sh < &shdr[ehdr->e_shnum]; ++sh) { DEBUG_PRINTF("section name: %s ( start: 0x%04x, size: 0x%04x)\n", str_table+sh->sh_name, sh->sh_offset, sh->sh_size ); if (strcmp(".toe", str_table+sh->sh_name) == 0) { DEBUG_PRINTF("section offset: %d\n", sh->sh_offset); toe_size += sh->sh_size; if ((toe_addr == 0) || (toe_addr > sh->sh_addr)) toe_addr = sh->sh_addr; } /* Disabled : Actually not needed, only good for testing if (strcmp(".bss", str_table+sh->sh_name) == 0) { DEBUG_PRINTF("zeroing .bss section:\n"); DEBUG_PRINTF("section offset: 0x%04x\n", sh->sh_offset); DEBUG_PRINTF("section size: 0x%04x\n", sh->sh_size); memset(ld_buffer + sh->sh_offset, 0, sh->sh_size); } */ #ifdef DEBUG if (strcmp(".note.spu_name", str_table+sh->sh_name) == 0) display_debug_output(elf_start, sh); #endif /*DEBUG*/ } /* * Load all PT_LOAD segments onto the SPE local store buffer. */ DEBUG_PRINTF("Segments: 0x%x\n", ehdr->e_phnum); for (ph = phdr, prev_ph = NULL; ph < &phdr[ehdr->e_phnum]; ++ph) { switch (ph->p_type) { case PT_LOAD: if (!overlay(ph, prev_ph)) { if (ph->p_filesz < ph->p_memsz) { DEBUG_PRINTF("padding loaded image with zeros:\n"); DEBUG_PRINTF("start: 0x%04x\n", ph->p_vaddr + ph->p_filesz); DEBUG_PRINTF("length: 0x%04x\n", ph->p_memsz - ph->p_filesz); memset(ld_buffer + ph->p_vaddr + ph->p_filesz, 0, ph->p_memsz - ph->p_filesz); } copy_to_ld_buffer(handle, ld_buffer, ph, toe_addr, toe_size); num_load_seg++; } break; case PT_NOTE: DEBUG_PRINTF("SPE_LOAD found PT_NOTE\n"); break; } } if (num_load_seg == 0) { DEBUG_PRINTF ("no segments to load"); errno = EINVAL; return -errno; } /* Remember where the code wants to be started */ ld_info->entry = ehdr->e_entry; DEBUG_PRINTF ("entry = 0x%x\n", ehdr->e_entry); return 0; } #ifdef DEBUG static void display_debug_output(Elf32_Ehdr *elf_start, Elf32_Shdr *sh) { typedef struct { unsigned long namesz; unsigned long descsz; unsigned long type; char name[8]; char lookupname[32]; } ELF_NOTE; ELF_NOTE *note = (ELF_NOTE *)((void *)elf_start+sh->sh_offset); printf ("Loading SPE program : %s\n", note->lookupname); printf ("SPU LS Entry Addr : 0x%05x\n", elf_start->e_entry); } #endif /*DEBUG*/ static int toe_check_syms(Elf32_Ehdr *ehdr, Elf32_Shdr *sh) { Elf32_Sym *sym, *sym_hdr, *sym_end; Elf32_Shdr *shdr; char *str_table; char *sym_name; int ret; shdr = (Elf32_Shdr*) ((char*) ehdr + ehdr->e_shoff); sym_hdr = (Elf32_Sym*) ((char*) ehdr + sh->sh_offset); sym_end = (Elf32_Sym*) ((char*) ehdr + sh->sh_offset + sh->sh_size); str_table = (char*)ehdr + shdr[sh->sh_link].sh_offset; ret = 0; for (sym = sym_hdr; sym < sym_end; sym++) if (sym->st_name) { sym_name = str_table + sym->st_name; if ((strncmp(sym_name, "_EAR_", 5) == 0) && (strcmp(sym_name, "_EAR_") != 0)) { /* * We have a prefix of _EAR_ followed by * something else. This is not currently * (and might not ever be) supported: for * a _EAR_foo, it requires a lookup of foo * in the ppu ELF file. */ fprintf(stderr, "Invalid _EAR_ symbol '%s'\n", sym_name); errno = EINVAL; ret = 1; } } return ret; } int _base_spe_toe_ear (spe_program_handle_t *speh) { Elf32_Ehdr *ehdr; Elf32_Shdr *shdr, *sh; char *str_table; char **ch; int ret; long toe_size; ehdr = (Elf32_Ehdr*) (speh->elf_image); shdr = (Elf32_Shdr*) ((char*) ehdr + ehdr->e_shoff); str_table = (char*)ehdr + shdr[ehdr->e_shstrndx].sh_offset; toe_size = 0; for (sh = shdr; sh < &shdr[ehdr->e_shnum]; ++sh) if (strcmp(".toe", str_table + sh->sh_name) == 0) toe_size += sh->sh_size; ret = 0; if (toe_size > 0) { for (sh = shdr; sh < &shdr[ehdr->e_shnum]; ++sh) if (sh->sh_type == SHT_SYMTAB || sh->sh_type == SHT_DYNSYM) ret = toe_check_syms(ehdr, sh); if (!ret && toe_size != 16) { /* Paranoia */ fprintf(stderr, "Unexpected toe size of %ld\n", toe_size); errno = EINVAL; ret = 1; } } if (!ret && toe_size) { /* * Allocate toe_shadow, and fill it with elf_image. */ speh->toe_shadow = malloc(toe_size); if (speh->toe_shadow) { ch = (char**) speh->toe_shadow; if (sizeof(char*) == 8) { ch[0] = (char*) speh->elf_image; ch[1] = 0; } else { ch[0] = 0; ch[1] = (char*) speh->elf_image; ch[2] = 0; ch[3] = 0; } } else { errno = ENOMEM; ret = 1; } } return ret; } libspe2-2.2.80-95/spebase/create.c0000644000175100017510000002650610704604414016036 0ustar arthurarthur/* * libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include "create.h" #include "spebase.h" struct fd_attr { const char *name; int mode; }; static const struct fd_attr spe_fd_attr[NUM_MBOX_FDS] = { [FD_MBOX] = { .name = "mbox", .mode = O_RDONLY }, [FD_MBOX_STAT] = { .name = "mbox_stat", .mode = O_RDONLY }, [FD_IBOX] = { .name = "ibox", .mode = O_RDONLY }, [FD_IBOX_NB] = { .name = "ibox", .mode = O_RDONLY |O_NONBLOCK }, [FD_IBOX_STAT] = { .name = "ibox_stat", .mode = O_RDONLY }, [FD_WBOX] = { .name = "wbox", .mode = O_WRONLY }, [FD_WBOX_NB] = { .name = "wbox", .mode = O_WRONLY|O_NONBLOCK }, [FD_WBOX_STAT] = { .name = "wbox_stat", .mode = O_RDONLY }, [FD_SIG1] = { .name = "signal1", .mode = O_WRONLY }, [FD_SIG2] = { .name = "signal2", .mode = O_WRONLY }, [FD_MFC] = { .name = "mfc", .mode = O_RDWR }, [FD_MSS] = { .name = "mss", .mode = O_RDWR }, }; static void *mapfileat(int dir, const char *filename, int size) { int fd_temp; void *ret; fd_temp = openat(dir, filename, O_RDWR); if (fd_temp < 0) { DEBUG_PRINTF("ERROR: Could not open SPE %s file.\n", filename); errno = EFAULT; return MAP_FAILED; } ret = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_temp, 0); close(fd_temp); return ret; } static int setsignotify(int dir, const char *filename) { int fd_sig, rc = 0; char one = '1'; fd_sig = openat(dir, filename, O_RDWR); if (fd_sig < 0) return -1; if (write(fd_sig, &one, sizeof(one)) != sizeof(one)) rc = -1; close(fd_sig); return 0; } void _base_spe_context_lock(spe_context_ptr_t spe, enum fd_name fdesc) { pthread_mutex_lock(&spe->base_private->fd_lock[fdesc]); } void _base_spe_context_unlock(spe_context_ptr_t spe, enum fd_name fdesc) { pthread_mutex_unlock(&spe->base_private->fd_lock[fdesc]); } int _base_spe_open_if_closed(struct spe_context *spe, enum fd_name fdesc, int locked) { if (!locked) _base_spe_context_lock(spe, fdesc); /* already open? */ if (spe->base_private->spe_fds_array[fdesc] != -1) { spe->base_private->spe_fds_refcount[fdesc]++; } else { spe->base_private->spe_fds_array[fdesc] = openat(spe->base_private->fd_spe_dir, spe_fd_attr[fdesc].name, spe_fd_attr[fdesc].mode); if (spe->base_private->spe_fds_array[(int)fdesc] > 0) spe->base_private->spe_fds_refcount[(int)fdesc]++; } if (!locked) _base_spe_context_unlock(spe, fdesc); return spe->base_private->spe_fds_array[(int)fdesc]; } void _base_spe_close_if_open(struct spe_context *spe, enum fd_name fdesc) { _base_spe_context_lock(spe, fdesc); if (spe->base_private->spe_fds_array[(int)fdesc] != -1 && spe->base_private->spe_fds_refcount[(int)fdesc] == 1) { spe->base_private->spe_fds_refcount[(int)fdesc]--; close(spe->base_private->spe_fds_array[(int)fdesc]); spe->base_private->spe_fds_array[(int)fdesc] = -1; } else if (spe->base_private->spe_fds_refcount[(int)fdesc] > 0) { spe->base_private->spe_fds_refcount[(int)fdesc]--; } _base_spe_context_unlock(spe, fdesc); } static int free_spe_context(struct spe_context *spe) { int i; if (spe->base_private->psmap_mmap_base != MAP_FAILED) { munmap(spe->base_private->psmap_mmap_base, PSMAP_SIZE); } else { if (spe->base_private->mfc_mmap_base != MAP_FAILED) munmap(spe->base_private->mfc_mmap_base, MFC_SIZE); if (spe->base_private->mssync_mmap_base != MAP_FAILED) munmap(spe->base_private->mssync_mmap_base, MSS_SIZE); if (spe->base_private->cntl_mmap_base != MAP_FAILED) munmap(spe->base_private->cntl_mmap_base, CNTL_SIZE); if (spe->base_private->signal1_mmap_base != MAP_FAILED) munmap(spe->base_private->signal1_mmap_base, SIGNAL_SIZE); if (spe->base_private->signal2_mmap_base != MAP_FAILED) munmap(spe->base_private->signal2_mmap_base, SIGNAL_SIZE); } if (spe->base_private->mem_mmap_base != MAP_FAILED) munmap(spe->base_private->mem_mmap_base, LS_SIZE); for (i = 0; i < NUM_MBOX_FDS; i++) { if (spe->base_private->spe_fds_array[i] >= 0) close(spe->base_private->spe_fds_array[i]); pthread_mutex_destroy(&spe->base_private->fd_lock[i]); } if (spe->base_private->fd_spe_dir >= 0) close(spe->base_private->fd_spe_dir); free(spe->base_private); free(spe); 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) { 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; } static int free_spe_gang_context(struct spe_gang_context *gctx) { if (gctx->base_private->fd_gang_dir >= 0) close(gctx->base_private->fd_gang_dir); free(gctx->base_private); free(gctx); return 0; } spe_gang_context_ptr_t _base_spe_gang_context_create(unsigned int flags) { 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_context_destroy(spe_context_ptr_t spe) { int ret = free_spe_context(spe); __spe_context_update_event(); return ret; } int _base_spe_gang_context_destroy(spe_gang_context_ptr_t gctx) { return free_spe_gang_context(gctx); } libspe2-2.2.80-95/spebase/mbox.c0000644000175100017510000002113210650125273015527 0ustar arthurarthur/* * libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include "create.h" #include "mbox.h" /** * SPE Mailbox Communication * ------------------------- */ static __inline__ int _base_spe_out_mbox_read_ps(spe_context_ptr_t spectx, unsigned int mbox_data[], int count) { volatile struct spe_spu_control_area *cntl_area = spectx->base_private->cntl_mmap_base; int total; int entries; _base_spe_context_lock(spectx, FD_MBOX); total = 0; while (total < count) { entries = cntl_area->SPU_Mbox_Stat & 0xFF; if (entries == 0) break; // no entries if (entries > count - total) entries = count - total; // don't read more than we need; while(entries--) { mbox_data[total] = cntl_area->SPU_Out_Mbox; total ++; } } _base_spe_context_unlock(spectx, FD_MBOX); return total; } int _base_spe_out_mbox_read(spe_context_ptr_t spectx, unsigned int mbox_data[], int count) { 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; } static __inline__ int _base_spe_in_mbox_write_ps(spe_context_ptr_t spectx, unsigned int *mbox_data, int count) { volatile struct spe_spu_control_area *cntl_area = spectx->base_private->cntl_mmap_base; int total = 0; unsigned int *aux; int space; _base_spe_context_lock(spectx, FD_WBOX); aux = mbox_data; while (total < count) { space = (cntl_area->SPU_Mbox_Stat >> 8) & 0xFF; if (space == 0) break; // no space if (space > count - total) space = count - total; // don't write more than we have while (space --) { cntl_area->SPU_In_Mbox = *aux++; total++; } } _base_spe_context_unlock(spectx, FD_WBOX); return total; } int _base_spe_in_mbox_write(spe_context_ptr_t spectx, unsigned int *mbox_data, int count, int behavior_flag) { int rc; int total; unsigned int *aux; struct pollfd fds; if (mbox_data == NULL || count < 1){ errno = EINVAL; return -1; } switch (behavior_flag) { case SPE_MBOX_ALL_BLOCKING: // write all, even if blocking total = rc = 0; if (spectx->base_private->flags & SPE_MAP_PS) { do { aux = mbox_data + total; total += _base_spe_in_mbox_write_ps(spectx, aux, count - total); if (total < count) { // we could not write everything, wait for space fds.fd = _base_spe_open_if_closed(spectx, FD_WBOX, 0); fds.events = POLLOUT; rc = poll(&fds, 1, -1); if (rc == -1 ) return -1; } } while (total < count); } else { while (total < 4*count) { rc = write(_base_spe_open_if_closed(spectx,FD_WBOX, 0), (const char *)mbox_data + total, 4*count - total); if (rc == -1) { break; } total += rc; } total /=4; } break; case SPE_MBOX_ANY_BLOCKING: // write at least one, even if blocking total = rc = 0; if (spectx->base_private->flags & SPE_MAP_PS) { do { total = _base_spe_in_mbox_write_ps(spectx, mbox_data, count); if (total == 0) { // we could not anything, wait for space fds.fd = _base_spe_open_if_closed(spectx, FD_WBOX, 0); fds.events = POLLOUT; rc = poll(&fds, 1, -1); if (rc == -1 ) return -1; } } while (total == 0); } else { rc = write(_base_spe_open_if_closed(spectx,FD_WBOX, 0), mbox_data, 4*count); total = rc/4; } break; case SPE_MBOX_ANY_NONBLOCKING: // only write, if non blocking total = rc = 0; // write directly if we map the PS else write via spufs if (spectx->base_private->flags & SPE_MAP_PS) { total = _base_spe_in_mbox_write_ps(spectx, mbox_data, count); } else { rc = write(_base_spe_open_if_closed(spectx,FD_WBOX_NB, 0), mbox_data, 4*count); if (rc == -1 && errno == EAGAIN) { rc = 0; errno = 0; } total = rc/4; } break; default: errno = EINVAL; return -1; } if (rc == -1) { errno = EIO; return -1; } return total; } int _base_spe_in_mbox_status(spe_context_ptr_t spectx) { 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; } int _base_spe_out_mbox_status(spe_context_ptr_t spectx) { 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; } int _base_spe_out_intr_mbox_status(spe_context_ptr_t spectx) { 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; } int _base_spe_out_intr_mbox_read(spe_context_ptr_t spectx, unsigned int mbox_data[], int count, int behavior_flag) { 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; } int _base_spe_signal_write(spe_context_ptr_t spectx, unsigned int signal_reg, unsigned int data ) { 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; } libspe2-2.2.80-95/spebase/lib_builtin.c0000644000175100017510000000630210652115147017061 0ustar arthurarthur/* * libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include "spebase.h" #include "lib_builtin.h" #include "default_c99_handler.h" #include "default_posix1_handler.h" #include "default_libea_handler.h" #define HANDLER_IDX(x) (x & 0xff) /* * Default SPE library call handlers for 21xx stop-and-signal. */ static void *handlers[256] = { [HANDLER_IDX(SPE_C99_CLASS)] = _base_spe_default_c99_handler, [HANDLER_IDX(SPE_POSIX1_CLASS)] = _base_spe_default_posix1_handler, [HANDLER_IDX(SPE_LIBEA_CLASS)] = _base_spe_default_libea_handler }; int _base_spe_callback_handler_register(void * handler, unsigned int callnum, unsigned int mode) { 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; } int _base_spe_callback_handler_deregister(unsigned int callnum ) { 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 ) { errno = 0; if (callnum > MAX_CALLNUM) { errno = EINVAL; return NULL; } if (handlers[callnum] == NULL) { errno = ESRCH; return NULL; } return handlers[callnum]; } int _base_spe_handle_library_callback(struct spe_context *spe, int callnum, unsigned int npc) { int (*handler)(void *, unsigned int); int rc; errno = 0; if (!handlers[callnum]) { DEBUG_PRINTF ("No SPE library handler registered for this call.\n"); errno=ENOSYS; return -1; } handler=handlers[callnum]; /* For emulated isolation mode, position the * npc so that the buffer for the PPE-assisted * library calls can be accessed. */ if (spe->base_private->flags & SPE_ISOLATE_EMULATE) npc = SPE_EMULATE_PARAM_BUFFER; rc = handler(spe->base_private->mem_mmap_base, npc); if (rc) { DEBUG_PRINTF ("SPE library call unsupported.\n"); errno=ENOSYS; return rc; } return 0; } libspe2-2.2.80-95/spebase/info.h0000644000175100017510000000207710600243027015522 0ustar arthurarthur/* * libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _info_h_ #define _info_h_ #include "spebase.h" #define THREADS_PER_BE 2 int _base_spe_count_physical_cpus(int cpu_node); int _base_spe_count_physical_spes(int cpu_node); int _base_spe_count_usable_spes(int cpu_node); #endif libspe2-2.2.80-95/libspe2.spec0000644000175100017510000001222510701420070015201 0ustar arthurarthur%define release %{_version} %define build_all 1 Name: libspe2 Version: 2.2.80 Release: %{release} License: LGPL Group: System Environment/Base URL: http://www.bsc.es/projects/deepcomputing/linuxoncell Source: http://www.bsc.es/projects/deepcomputing/linuxoncell/development/release2.0/libspe/%{name}-%{version}-%{release}.tar.gz Buildroot: %{_tmppath}/libspe Exclusivearch: ppc ppc64 noarch Summary: SPE Runtime Management Library # to build the wrapper, call rpmbuild with --define="with_wrapper 1" %define WITH_WRAPPER %{?with_wrapper:%with_wrapper}%{!?with_wrapper:0} %if %{build_all} %define build_common 1 %else %ifarch ppc %define build_common 1 %else %define build_common 0 %endif %endif %ifarch noarch %define sysroot %{nil} %define set_optflags %{nil} %else %define sysroot %{nil} %define set_optflags OPTFLAGS="%{optflags}" %endif %define sysroot %{nil} %define set_optflags OPTFLAGS="%{optflags}" %ifarch ppc %define _libdir /usr/lib %endif %ifarch ppc64 %define _libdir /usr/lib64 %endif %define _adabindingdir /usr/adainclude %define _includedir2 /usr/spu/include %define _initdir /etc/init.d %define _unpackaged_files_terminate_build 0 %if %{WITH_WRAPPER} %package -n libspe Summary: SPE Runtime Management Wrapper Library Group: Development/Libraries Requires: %{name} = %{version} %endif %package devel Summary: SPE Runtime Management Library Group: Development/Libraries Requires: %{name} = %{version} %if %{WITH_WRAPPER} %package -n libspe-devel Summary: SPE Runtime Management Library Group: Development/Libraries Requires: %{name} = %{version} %endif %if %{build_common} %package -n elfspe2 Summary: Helper for standalong SPE applications Group: Applications/System Requires: %{name} = %{version} %endif %if %{build_common} %package adabinding Summary : Ada package files porting libspe headers Group: Development/Libraries Requires: %{name} = %{version} %endif %description SPE Runtime Management Library for the Cell Broadband Engine Architecture. %if %{WITH_WRAPPER} %description -n libspe Header and object files for SPE Runtime Management Wrapoer Library. %endif %description devel Header and object files for SPE Runtime Management Library. %if %{WITH_WRAPPER} %description -n libspe-devel Header and object files for SPE Runtime Management Library. %endif %if %{build_common} %description adabinding Ada package files porting libspe headers Management Library. %endif %if %{build_common} %description -n elfspe2 This tool acts as a standalone loader for spe binaries. %endif %prep %setup %build make SYSROOT=%{sysroot} %{set_optflags} prefix=%{_prefix} libdir=%{_libdir} %if %{build_common} make elfspe-all SYSROOT=%{sysroot} %{set_optflags} prefix=%{_prefix} libdir=%{_libdir} %endif %install rm -rf $RPM_BUILD_ROOT%{sysroot} make install DESTDIR=$RPM_BUILD_ROOT SYSROOT=%{sysroot} prefix=%{_prefix} libdir=%{_libdir} speinclude=%{_includedir2} %if %{build_common} make elfspe-install DESTDIR=$RPM_BUILD_ROOT SYSROOT=%{sysroot} prefix=%{_prefix} libdir=%{_libdir} speinclude=%{_includedir2} %endif mkdir -p $RPM_BUILD_ROOT%{sysroot}%{_initdir} cat > $RPM_BUILD_ROOT%{sysroot}%{_initdir}/elfspe <<"EOF" #!/bin/bash # # /etc/rc.d/init.d/elfspe # # registers elfspe handler # # chkconfig: 345 1 1 # description: executes elfspe-register # Source function library. . /etc/init.d/functions start() { echo -n "Starting elfspe: " sh /usr/bin/elfspe-register return 0 } stop() { echo -n "Shutting down elfspe: " sh /usr/bin/elfspe-unregister return 0 } case "$1" in start) start ;; stop) stop ;; status) ;; restart) stop start ;; reload) ;; condrestart) [ -f /var/lock/subsys/elspe ] && restart || : ;; *) echo "Usage: elfspe {start|stop|status|reload|restart" exit 1 ;; esac exit $? EOF chmod +x $RPM_BUILD_ROOT%{sysroot}%{_initdir}/elfspe %clean rm -rf $RPM_BUILD_ROOT %post -p /sbin/ldconfig %postun -p /sbin/ldconfig %if %{build_common} %preun -n elfspe2 [ -f %{_initdir}/elfspe ] && /sbin/chkconfig --del elfspe %post -n elfspe2 [ -f %{_initdir}/elfspe ] && /sbin/chkconfig --add elfspe [ -f %{_bindir}/elfspe-register ] && %{_bindir}/elfspe-register %endif %files %defattr(-,root,root) %{sysroot}%{_libdir}/*2.so.* %if %{WITH_WRAPPER} %files -n libspe %defattr(-,root,root) %{sysroot}%{_libdir}/libspe.so.* %endif %files devel %defattr(-,root,root) %{sysroot}%{_libdir}/*2.so %{sysroot}%{_libdir}/*2.a %{sysroot}%{_includedir}/*2*.h %{sysroot}%{_includedir}/cbea_map.h %{sysroot}%{_includedir2}/*.h %{sysroot}%{_libdir}/pkgconfig/libspe2.pc %if %{WITH_WRAPPER} %files -n libspe-devel %defattr(-,root,root) %{sysroot}%{_libdir}/libspe.so %{sysroot}%{_libdir}/libspe.a %{sysroot}%{_includedir}/libspe.h %endif %if %{build_common} %files -n elfspe2 %defattr(-,root,root) %{sysroot}%{_bindir}/elfspe-register %{sysroot}%{_bindir}/elfspe-unregister %{sysroot}%{_bindir}/elfspe %{sysroot}/etc/init.d/elfspe %endif %if %{build_common} %files adabinding %defattr(-,root,root) %{sysroot}%{_adabindingdir}/libspe2.ads %{sysroot}%{_adabindingdir}/libspe2_types.ads %{sysroot}%{_adabindingdir}/cbea_map.ads %{sysroot}%{_adabindingdir}/README-libspe2 %endif %changelog * Thu Nov 24 2005 - Arnd Bergmann 1.0.1-3 - initial spec file for fc5 libspe2-2.2.80-95/COPYING0000644000175100017510000006350010600243027014025 0ustar arthurarthur GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! libspe2-2.2.80-95/libspe2.h0000644000175100017510000001336610667524000014516 0ustar arthurarthur/* * SPE Runtime Management Library, Version 2.0 * This library constitutes the standardized low-level application * programming interface for application access to the Cell Broadband * Engineís Synergistic Processing Elements (SPEs). * * The usage of this library requires that the application programmer * is familiar with the CBE architecture as described in ìCell * Broadband Engine Architecture, Version 1.0î. * * Copyright (C) 2006 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * libspe2.h contains the public API funtions */ #ifndef libspe2_h #define libspe2_h #ifdef __cplusplus extern "C" { #endif #include #include /* * GLOBAL SYMBOLS AND STRUCTURES * libspe2-types header file */ #include "libspe2-types.h" /* *--------------------------------------------------------- * * API functions * *--------------------------------------------------------- */ /* * spe_context_create */ spe_context_ptr_t spe_context_create(unsigned int flags, spe_gang_context_ptr_t gang); /* * spe_context_create_affinity */ spe_context_ptr_t spe_context_create_affinity(unsigned int flags, spe_context_ptr_t affinity_neighbor, spe_gang_context_ptr_t gang); /* * spe_context_destroy */ int spe_context_destroy (spe_context_ptr_t spe); /* * spe_gang_context_create */ spe_gang_context_ptr_t spe_gang_context_create (unsigned int flags); /* * spe_gang_context_destroy */ int spe_gang_context_destroy (spe_gang_context_ptr_t gang); /* * spe_image_open */ spe_program_handle_t * spe_image_open (const char *filename); /* * spe_image_close */ int spe_image_close (spe_program_handle_t *program); /* * spe_load_program */ int spe_program_load (spe_context_ptr_t spe, spe_program_handle_t *program); /* * spe_context_run */ int spe_context_run (spe_context_ptr_t spe, unsigned int *entry, unsigned int runflags, void *argp, void *envp, spe_stop_info_t *stopinfo); /* * spe_stop_info_read */ int spe_stop_info_read (spe_context_ptr_t spe, spe_stop_info_t *stopinfo); /* * spe_event_handler_create */ spe_event_handler_ptr_t spe_event_handler_create(void); /* * spe_event_handler_destroy */ int spe_event_handler_destroy (spe_event_handler_ptr_t evhandler); /* * spe_event_handler_register */ int spe_event_handler_register(spe_event_handler_ptr_t evhandler, spe_event_unit_t *event); /* * spe_event_handler_deregister */ int spe_event_handler_deregister(spe_event_handler_ptr_t evhandler, spe_event_unit_t *event); /* * spe_event_wait */ int spe_event_wait(spe_event_handler_ptr_t evhandler, spe_event_unit_t *events, int max_events, int timeout); /* * MFCIO Proxy Commands */ int spe_mfcio_put (spe_context_ptr_t spe, unsigned int ls, void *ea, unsigned int size, unsigned int tag, unsigned int tid, unsigned int rid); int spe_mfcio_putb (spe_context_ptr_t spe, unsigned int ls, void *ea, unsigned int size, unsigned int tag, unsigned int tid, unsigned int rid); int spe_mfcio_putf (spe_context_ptr_t spe, unsigned int ls, void *ea, unsigned int size, unsigned int tag, unsigned int tid, unsigned int rid); int spe_mfcio_get (spe_context_ptr_t spe, unsigned int ls, void *ea, unsigned int size, unsigned int tag, unsigned int tid, unsigned int rid); int spe_mfcio_getb (spe_context_ptr_t spe, unsigned int ls, void *ea, unsigned int size, unsigned int tag, unsigned int tid, unsigned int rid); int spe_mfcio_getf (spe_context_ptr_t spe, unsigned int ls, void *ea, unsigned int size, unsigned int tag, unsigned int tid, unsigned int rid); /* * MFCIO Tag Group Completion */ int spe_mfcio_tag_status_read(spe_context_ptr_t spe, unsigned int mask, unsigned int behavior, unsigned int *tag_status); /* * SPE Mailbox Facility */ int spe_out_mbox_read (spe_context_ptr_t spe, unsigned int *mbox_data, int count); int spe_out_mbox_status (spe_context_ptr_t spe); int spe_in_mbox_write (spe_context_ptr_t spe, unsigned int *mbox_data, int count, unsigned int behavior); int spe_in_mbox_status (spe_context_ptr_t spe); int spe_out_intr_mbox_read (spe_context_ptr_t spe, unsigned int *mbox_data, int count, unsigned int behavior); int spe_out_intr_mbox_status (spe_context_ptr_t spe); /* * Multisource Sync Facility */ int spe_mssync_start(spe_context_ptr_t spe); int spe_mssync_status(spe_context_ptr_t spe); /* * SPU SIgnal Notification Facility */ int spe_signal_write (spe_context_ptr_t spe, unsigned int signal_reg, unsigned int data); /* * spe_ls_area_get */ void * spe_ls_area_get (spe_context_ptr_t spe); /* * spe_ls_size_get */ int spe_ls_size_get (spe_context_ptr_t spe); /* * spe_ps_area_get */ void * spe_ps_area_get (spe_context_ptr_t spe, enum ps_area area); /* * spe_callback_handler_register */ int spe_callback_handler_register (void *handler, unsigned int callnum, unsigned int mode); /* * spe_callback_handler_deregister */ int spe_callback_handler_deregister (unsigned int callnum); /* * spe_callback_handler_query */ void * spe_callback_handler_query(unsigned int callnum); /* * spe_info_get */ int spe_cpu_info_get(int info_requested, int cpu_node); #ifdef __cplusplus } #endif #endif /*libspe2_h*/ libspe2-2.2.80-95/libspe2.pc.in0000644000175100017510000000042510624262650015271 0ustar arthurarthurprefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: @name@ Description: A wrapper library to adapt the JSRE SPU usage model to SPUFS Version: @version@ Requires: Conflicts: Libs: -L${libdir} -lspe2 -lrt -lpthread Cflags: -I${includedir} libspe2-2.2.80-95/Makefile0000644000175100017510000001372410643177045014452 0ustar arthurarthur#* #* libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS #* Copyright (C) 2005 IBM Corp. #* #* This library is free software; you can redistribute it and/or modify it #* under the terms of the GNU Lesser General Public License as published by #* the Free Software Foundation; either version 2.1 of the License, #* or (at your option) any later version. #* #* This library is distributed in the hope that it will be useful, but #* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY #* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public #* License for more details. #* #* You should have received a copy of the GNU Lesser General Public License #* along with this library; if not, write to the Free Software Foundation, #* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #* TOP=. include $(TOP)/make.defines libspe2_OBJS := libspe2.o CFLAGS += -I$(TOP)/spebase CFLAGS += -I$(TOP)/speevent PACKAGE := libspe2 VERSION := $(MAJOR_VERSION).$(MINOR_VERSION) RELEASE := $(shell svnversion) FULLNAME := $(PACKAGE)-$(VERSION) PACKAGE_VER := $(FULLNAME)-$(RELEASE) TARBALL := $(SOURCES)$(PACKAGE_VER).tar.gz SOURCEFILES := $(TARBALL) edit = @sed \ -e 's,@prefix@,$(prefix),g' \ -e 's,@exec_prefix@,$(exec_prefix),g' \ -e 's,@libdir@,$(libdir),g' \ -e 's,@name@,$(PACKAGE),g' \ -e 's,@includedir@,$(includedir),g' \ -e 's,@version@,$(VERSION),g' all: $(libspe2_SO) $(libspe2_A) libspe12-all dist: $(TARBALL) pushall: quilt push -a ; true popall: quilt pop -a ; true base-all: $(MAKE) -C spebase all event-all: $(MAKE) -C speevent all elfspe-all: $(MAKE) -C elfspe all libspe12-all: $(MAKE) -C libspe12 all install: libspe12-install $(INSTALL_DIR) $(ROOT)$(libdir) $(INSTALL_DIR) $(ROOT)$(libdir)/pkgconfig $(INSTALL_DATA) $(libspe2_A) $(ROOT)$(libdir)/$(libspe2_A) $(INSTALL_PROGRAM) $(libspe2_SO) $(ROOT)$(libdir)/$(libspe2_SO) $(INSTALL_LINK) $(libspe2_SO) $(ROOT)$(libdir)/$(libspe2_SONAME) $(INSTALL_DATA) libspe2.pc $(ROOT)$(libdir)/pkgconfig $(INSTALL_LINK) $(libspe2_SONAME) $(ROOT)$(libdir)/libspe2.so $(INSTALL_DIR) $(ROOT)$(includedir) $(INSTALL_DATA) libspe2.h $(ROOT)$(includedir)/libspe2.h $(INSTALL_DATA) libspe2-types.h $(ROOT)$(includedir)/libspe2-types.h $(INSTALL_DIR) $(ROOT)$(includedir) $(INSTALL_DATA) spebase/cbea_map.h $(ROOT)$(includedir)/cbea_map.h $(INSTALL_DIR) $(ROOT)$(speinclude) $(INSTALL_DATA) spebase/cbea_map.h $(ROOT)$(speinclude)/cbea_map.h $(INSTALL_DIR) $(ROOT)$(adabindingdir) $(INSTALL_DATA) ada/README $(ROOT)$(adabindingdir)/README-libspe2 $(INSTALL_DATA) ada/cbea_map.ads $(ROOT)$(adabindingdir)/cbea_map.ads $(INSTALL_DATA) ada/libspe2.ads $(ROOT)$(adabindingdir)/libspe2.ads $(INSTALL_DATA) ada/libspe2_types.ads $(ROOT)$(adabindingdir)/libspe2_types.ads elfspe-install: $(MAKE) -C elfspe install libspe12-install: $(MAKE) -C libspe12 install tests: tests/Makefile make -C tests ada : ada/Makefile make -C ada tags: $(CTAGS) -R . libspe2.pc: Makefile $(TOP)/libspe2.pc.in @rm -f $@ $@.tmp $(edit) $(TOP)/$@.in >$@.tmp @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} $(libspe2_A): $(libspe2_OBJS) base-all event-all $(CROSS)ar -r $(libspe2_A) $(libspe2_OBJS) spebase/*.o speevent/*.o $(libspe2_OBJS) PATCHES := `cat series | grep -v ^\#` #RPMBUILD = ppc32 rpmbuild --target=ppc RPMBUILD = rpmbuild PWD := $(shell pwd) RPM := $(PWD)/.. SOURCES = $(PWD)/ RPMS = $(RPM)/RPMS/ SRPMS = $(RPM)/SRPMS/ BUILD = $(RPM)/BUILD/ TMP = $(RPM)/tmp/ SPEC ?= $(PACKAGE).spec RPMBUILD ?= rpmbuild checkenv: @if [ ""x = "$(PACKAGE)"x \ -o ""x = "$(SOURCEFILES)"x \ -o ""x = "$(SPEC)"x ] ; then \ echo "inconsistant make file" false; fi $(PWD)/.rpmmacros: mkdir -p $(SOURCES) $(RPMS) $(SRPMS) $(BUILD) echo -e \%_topdir $(RPM)\\n\%_sourcedir $(PWD)\\n\%_tmppath %_topdir/tmp\\n\%_version $(RELEASE) > $@ rpm: dist checkenv $(RPM)/$(PACKAGE)-stamp $(RPM)/$(PACKAGE)-stamp: $(PWD)/.rpmmacros $(SOURCEFILES) $(SPEC) HOME=$(PWD) $(RPMBUILD) -ba $(SPEC) $(RPMFLAGS) touch $@ crossrpm: dist checkenv $(RPM)/$(PACKAGE)-cross-stamp $(RPM)/$(PACKAGE)-cross-stamp: $(PWD)/.rpmmacros $(SOURCEFILES) $(SPEC) HOME=$(PWD) $(RPMBUILD) -ba $(SPEC) --target=noarch $(RPMFLAGS) touch $@ .PHONY: checkenv rpm crossrpm rpms: clean rpm rpm32 rpm32: HOME=$(PWD) $(RPMBUILD) --target=ppc -ba $(SPEC) $(RPMFLAGS) rpm64: HOME=$(PWD) $(RPMBUILD) --target=ppc64 -ba $(SPEC) $(RPMFLAGS) $(TARBALL): clean ln -s . $(FULLNAME) tar -czhf $@ --exclude=$(PACKAGE_VER).tar.gz \ --exclude=$(FULLNAME)/$(FULLNAME) \ --exclude=CVS --exclude .pc --exclude '.*.swp' --exclude '*~' --exclude '.#*' \ --exclude=$(FULLNAME)/spegang \ --exclude=$(FULLNAME)/spethread \ --exclude=$(FULLNAME)/tests_hidden \ --exclude=$(FULLNAME)/patches \ --exclude=.svn \ $(FULLNAME) rm $(FULLNAME) doc: text pdf text: xml cd doc; xsltproc extractfunctions.xslt ../xml/all.xml > functions.txt xml: clean doxygen doc/DoxyfileRef cd xml; xsltproc combine.xslt index.xml >all.xml pdf: apiref detail detail: clean doxygen doc/Doxyfile cd latex; make; cp refman.pdf ../doc/detail.pdf apiref: clean cd doc/img; make doxygen doc/DoxyfileRef cp doc/img/*.pdf latex cd latex; make; cp refman.pdf ../doc/apiref.pdf clean: base-clean event-clean elfspe-clean libspe12-clean rm *.diff ; true rm -rf $(libspe2_A) $(libspe2_SO) $(libspe2_OBJS) rm -f $(TARBALL) rm -f $(FULLNAME) rm -f doc/*.pdf rm -f doc/functions.txt rm -rf xml rm -rf html rm -rf latex rm -f libspe2.pc make -C tests clean make -C ada clean base-clean: $(MAKE) -C spebase clean event-clean: $(MAKE) -C speevent clean elfspe-clean: $(MAKE) -C elfspe clean libspe12-clean: $(MAKE) -C libspe12 clean distclean: clean rm -rf latex rm -rf html .PHONY: all clean tests tags libspe2-2.2.80-95/make.defines0000644000175100017510000000446610701420070015251 0ustar arthurarthur#* #* libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS #* Copyright (C) 2005 IBM Corp. #* #* This library is free software; you can redistribute it and/or modify it #* under the terms of the GNU Lesser General Public License as published by #* the Free Software Foundation; either version 2.1 of the License, #* or (at your option) any later version. #* #* This library is distributed in the hope that it will be useful, but #* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY #* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public #* License for more details. #* #* You should have received a copy of the GNU Lesser General Public License #* along with this library; if not, write to the Free Software Foundation, #* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #* X86 = $(shell if ! uname -m | grep ppc ; then echo 1 ; fi) CROSS_COMPILE = $(shell if ! grep Broadband /proc/cpuinfo ; then echo 1 ; fi) ifeq "$(X86)" "1" CROSS ?= /opt/cell/bin/ppu- EXTRA_CFLAGS = -m32 -mabi=altivec # RPM defined default flags may not work with this cross-compiler override OPTFLAGS = endif ifeq "$(CROSS_COMPILE)" "1" SYSROOT ?= ../../../sysroot prefix ?= /usr else prefix ?= /usr/local endif SPU_CROSS = spu- exec_prefix = ${prefix} bindir = ${exec_prefix}/bin libdir = ${exec_prefix}/lib includedir = ${prefix}/include speinclude = ${prefix}/spu/include adabindingdir = ${prefix}/adainclude DESTDIR := ROOT := ${DESTDIR}${SYSROOT} INSTALL := /usr/bin/install -c INSTALL_PROGRAM := ${INSTALL} -m 755 INSTALL_DATA := ${INSTALL} -m 644 INSTALL_LINK := ln -sf INSTALL_DIR := ${INSTALL} -d -m 755 MAJOR_VERSION := 2 MINOR_VERSION := 2.80 libspe2_A := libspe2.a libspe2_SO := libspe2.so.${MAJOR_VERSION}.${MINOR_VERSION} libspe2_SONAME := libspe2.so.${MAJOR_VERSION} CC := ${CROSS}gcc CTAGS := ctags CFLAGS := -O2 -Wall -I. -fPIC -I$(TOP)/include -fexceptions -std=gnu99 \ -Wformat -Wdisabled-optimization \ -Wundef -Wshadow -Wcast-align -Wwrite-strings \ -Wmissing-prototypes -Wmissing-declarations \ -Wmissing-noreturn -Wredundant-decls \ -Wnested-externs -Winline -Wformat \ ${EXTRA_CFLAGS} ${OPTFLAGS} SPU_CC = $(SPU_CROSS)gcc SPU_CFLAGS = #DEBUG=1 ifdef DEBUG CFLAGS += -DDEBUG -g endif libspe2-2.2.80-95/.project0000644000175100017510000000031010600243027014427 0ustar arthurarthur libspe2 libspe2-2.2.80-95/include/0000755000175100017510000000000010707604273014425 5ustar arthurarthurlibspe2-2.2.80-95/include/sys/0000755000175100017510000000000010707604273015243 5ustar arthurarthurlibspe2-2.2.80-95/include/sys/spu.h0000644000175100017510000000165610600243027016217 0ustar arthurarthur#ifndef __SYS_SPU_H #define __SYS_SPU_H #include #include #include #ifndef __NR_spu_run #define __NR_spu_run 278 #endif #ifndef __NR_spu_create #define __NR_spu_create 279 #endif #define SPU_CREATE_EVENTS_ENABLED 0x0001 #define SPU_CREATE_GANG 0x0002 #define SPU_CREATE_NOSCHED 0x0004 #define SPU_CREATE_ISOLATE 0x0008 #define SPU_CREATE_AFFINITY_SPU 0x0010 #define SPU_CREATE_AFFINITY_MEM 0x0020 static inline int spu_run(int fd, unsigned int *npc, unsigned int *status) { return syscall(__NR_spu_run, fd, npc, status); } static int spu_create(const char * path, int flags, mode_t mode, ...) { va_list vargs; int fd; if (flags & SPU_CREATE_AFFINITY_SPU) { va_start(vargs, mode); fd = va_arg(vargs, int); va_end(vargs); return syscall(__NR_spu_create, path, flags, mode, fd); } else { return syscall(__NR_spu_create, path, flags, mode); } } #endif libspe2-2.2.80-95/ada/0000755000175100017510000000000010707604273013527 5ustar arthurarthurlibspe2-2.2.80-95/ada/testsingle.adb0000644000175100017510000000320310642143371016351 0ustar arthurarthur -- -- test functions: -- spe_context_create -- spe_image_open -- spe_program_load -- spe_context_run -- spe_context_destroy -- spe_image_close -- with System; with Ada.Text_IO; with Interfaces.C; with libspe2; with libspe2_types; procedure testsingle is use System; use Ada.Text_IO; use Interfaces.C; use libspe2; use libspe2_types; ctx : spe_context_ptr_t; flags : unsigned := 0; gang : spe_gang_context_ptr_t; program : spe_program_handle_t; argp : addr_ptr := Null; envp : addr_ptr := Null; rc : Integer; spe_entry : unsigned := SPE_DEFAULT_ENTRY; spe_entry_ptr : unsigned_ptr := new unsigned'(spe_entry); stop_info_ptr : spe_stop_info_ptr := new spe_stop_info; filename : String (1 .. 5) := "hello"; filename_c : char_array (1 .. 6); begin filename_c := To_C (filename, True); program := spe_image_open(filename_c); if program = NULL then Put_Line("spe_image_open failed!"); end if; gang := Null; ctx := spe_context_create(flags, gang); if ctx = NULL then Put_Line("spe_context_create failed!"); end if; rc := spe_program_load(ctx, program); if rc /= 0 then Put_Line("spe_program_load failed!"); end if; rc := spe_context_run(ctx, spe_entry_ptr, 0, argp, envp, stop_info_ptr); Put_Line("exit_code: " & Integer'Image(stop_info_ptr.spe_exit_code)); if rc /= 0 then Put_Line("spe_context_run failed!"); end if; rc := spe_context_destroy (ctx); if rc /= 0 then Put_Line("spe_context_destroy failed!"); end if; rc := spe_image_close(program); if rc /= 0 then Put_Line("spe_image_close failed!"); end if; end testsingle; libspe2-2.2.80-95/ada/single.sh0000644000175100017510000000017710642143371015344 0ustar arthurarthurspu-gcc helloworld.c -o hello ppu-gcc -c libspe2.ads libspe2_types.ads ppu-gnatmake testsingle.adb -o testsingle -largs -lspe2 libspe2-2.2.80-95/ada/Makefile0000644000175100017510000000254410644400150015160 0ustar arthurarthur#* #* libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS #* Copyright (C) 2005 IBM Corp. #* #* This library is free software; you can redistribute it and/or modify it #* under the terms of the GNU Lesser General Public License as published by #* the Free Software Foundation; either version 2.1 of the License, #* or (at your option) any later version. #* #* This library is distributed in the hope that it will be useful, but #* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY #* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public #* License for more details. #* #* You should have received a copy of the GNU Lesser General Public License #* along with this library; if not, write to the Free Software Foundation, #* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #* TOP=.. include $(TOP)/make.defines adabindings := libspe2 libspe2_types cbea_map\ testsingle spu_images := hello all: adabinding tests spu_programs adabinding : libspe2.ads libspe2_types.ads cbea_map.ads $(CC) -c cbea_map.ads $(CC) -c libspe2.ads $(CC) -c libspe2_types.ads tests : testsingle.adb $(CROSS)gnatmake -g $^ spu_programs: hello hello: helloworld.c $(SPU_CC) $(SPU_CFLAGS) $^ -o $@ install: $(adabinding) clean: rm -f $(adabindings) rm -f $(spu_images) rm -f *.o *.ali b~* libspe2-2.2.80-95/ada/helloworld.c0000644000175100017510000000012510642143371016037 0ustar arthurarthur#include main() { printf("Spu says hello!\n"); return 42; } libspe2-2.2.80-95/ada/libspe2_types.ads0000644000175100017510000001432210643145366017010 0ustar arthurarthur-- -- Definition of data types and constants -- with System; with Interfaces.C; package libspe2_types is use System; use Interfaces.C; type addr_ptr is access Address; type int_ptr is access Integer; type unsigned_ptr is access unsigned; -- SPE program handle -- Structure spe_program_handle per CESOF specification -- libspe2 applications usually only keep a pointer -- to the program handle and do not use the structure -- directly. type spe_program_handle is record handle_size : unsigned; elf_image_ptr : addr_ptr; toe_shadow_ptr : addr_ptr; end record; type spe_program_handle_t is access spe_program_handle; -- SPE context -- The SPE context is one of the base data structures for -- the libspe2 implementation. It holds all persistent information -- about a "logical SPE" used by the application. This data -- structure should not be accessed directly, but the application -- uses a pointer to an SPE context as an identifier for the -- "logical SPE" it is dealing with through libspe2 API calls. type spe_context is record handle : spe_program_handle; base_private : addr_ptr; event_private : addr_ptr; end record; type spe_context_ptr_t is access spe_context; -- SPE gang context -- The SPE gang context is one of the base data structures for -- the libspe2 implementation. It holds all persistent information -- about a group of SPE contexts that should be treated as a gang, -- i.e., be execute together with certain properties. This data -- structure should not be accessed directly, but the application -- uses a pointer to an SPE gang context as an identifier for the -- SPE gang it is dealing with through libspe2 API calls. type spe_gang_context is record base_private : addr_ptr; event_private : addr_ptr; end record; type spe_gang_context_ptr_t is access spe_gang_context; type index is range 1 .. 8; type spe_stop_info (reason: index := 1) is record spu_status : Integer; reserved : Integer; case reason is when 1 => spe_exit_code : Integer; when 2 => spe_signal_code : Integer; when 3 => spe_runtime_error : Integer; when 4 => spe_runtime_exception : Integer; when 5 => spe_runtime_fatal : Integer; when 6 => spe_callback_error : Integer; when 7 => reserved_ptr : addr_ptr; when 8 => reserved_u64 : unsigned_long; end case; end record; for spe_stop_info use record reason at 0 range 0 .. 31; reserved at 4 range 0 .. 31;-- only for 8 bytes alignment spe_exit_code at 8 range 0 .. 31; spe_signal_code at 8 range 0 .. 31; spe_runtime_error at 8 range 0 .. 31; spe_runtime_exception at 8 range 0 .. 31; spe_runtime_fatal at 8 range 0 .. 31; spe_callback_error at 8 range 0 .. 31; reserved_ptr at 8 range 0 .. 63; reserved_u64 at 8 range 0 .. 63; spu_status at 16 range 0 .. 31; end record; for spe_stop_info'size use 5*32; type spe_stop_info_ptr is access spe_stop_info; type spe_event_handler_t is new Integer; type spe_event_handler_ptr_t is new addr_ptr; type spe_event_data_t is record ptr : addr_ptr; -- FIXME: union without discriminant -- u32 : unsigned; -- u64 : unsigned_long; end record; for spe_event_data_t'Size use 64; type spe_event_unit_t is record events : unsigned; spe : spe_context_ptr_t; data : spe_event_data_t; end record; type spe_event_unit_t_ptr is access spe_event_unit_t; -- -- API symbolic constants -- type ps_area is (SPE_MSSYNC_AREA, SPE_MFC_COMMAND_AREA, SPE_CONTROL_AREA, SPE_SIG_NOTIFY_1_AREA, SPE_SIG_NOTIFY_2_AREA); -- -- Flags for spe_context_create -- SPE_CFG_SIGNOTIFY1_OR : constant unsigned := 16#00000010#; SPE_CFG_SIGNOTIFY2_OR : constant unsigned := 16#00000020#; SPE_MAP_PS : constant unsigned := 16#00000040#; SPE_ISOLATE : constant unsigned := 16#00000080#; SPE_EVENTS_ENABLE : constant unsigned := 16#00001000#; SPE_AFFINITY_MEMORY : constant unsigned := 16#00002000#; -- -- Symbolic constants for stop reasons -- as returned in spe_stop_info_t SPE_EXIT : constant Integer := 1; SPE_STOP_AND_SIGNAL : constant Integer := 2; SPE_RUNTIME_ERROR : constant Integer := 3; SPE_RUNTIME_EXCEPTION : constant Integer := 4; SPE_RUNTIME_FATAL : constant Integer := 5; SPE_CALLBACK_ERROR : constant Integer := 6; -- -- Runtime errors -- SPE_SPU_STOPPED_BY_STOP : constant unsigned := 16#02#;-- INTERNAL USE ONLY SPE_SPU_HALT : constant unsigned := 16#04#; SPE_SPU_WAITING_ON_CHANNEL : constant unsigned := 16#08#;-- INTERNAL USE ONLY SPE_SPU_SINGLE_STEP : constant unsigned := 16#10#; SPE_SPU_INVALID_INSTR : constant unsigned := 16#20#; SPE_SPU_INVALID_CHANNEL : constant unsigned := 16#40#; -- -- Runtime exceptions -- SPE_DMA_ALIGNMENT : constant unsigned := 16#0008#; SPE_DMA_SEGMENTATION : constant unsigned := 16#0020#; SPE_DMA_STORAGE : constant unsigned := 16#0040#; -- -- Supported SPE events -- SPE_EVENT_OUT_INTR_MBOX: constant unsigned := 16#00000001#; SPE_EVENT_IN_MBOX : constant unsigned := 16#00000002#; SPE_EVENT_TAG_GROUP : constant unsigned := 16#00000004#; SPE_EVENT_SPE_STOPPED : constant unsigned := 16#00000008#; SPE_EVENT_ALL_EVENTS : constant unsigned := 16#0000000F#; -- -- Behavior flags for mailbox read/write functions -- SPE_MBOX_ALL_BLOCKING : constant unsigned := 1; SPE_MBOX_ANY_BLOCKING : constant unsigned := 2; SPE_MBOX_ANY_NONBLOCKING : constant unsigned := 3; -- -- Behavior flags tag status functions -- SPE_TAG_ALL : constant unsigned := 1; SPE_TAG_ANY : constant unsigned := 2; SPE_TAG_IMMEDIATE : constant unsigned := 3; -- -- Flags for _base_spe_context_run -- SPE_DEFAULT_ENTRY : constant unsigned := 2**int'Size-1;-- UINT_MAX on spe -- 128b user data for r3-5. -- SPE_RUN_USER_REGS : constant Integer := 16#00000001#; SPE_NO_CALLBACKS : constant Integer := 16#00000002#; -- -- -- SPE_CALLBACK_NEW : constant unsigned := 1; SPE_CALLBACK_UPDATE : constant unsigned := 2; -- -- -- SPE_COUNT_PHYSICAL_CPU_NODES : constant Integer := 1; SPE_COUNT_PHYSICAL_SPES : constant Integer := 2; SPE_COUNT_USABLE_SPES : constant Integer := 3; -- -- Signal Targets -- SPE_SIG_NOTIFY_REG_1 : constant unsigned := 1; SPE_SIG_NOTIFY_REG_2 : constant unsigned := 2; end libspe2_types; libspe2-2.2.80-95/ada/README0000644000175100017510000000211310644400150014370 0ustar arthurarthurUsage of Ada binding package files There are three Ada binding package files under this directory: cbea_map.ads, libspe2_types.ads and libspe2.ads. The cbea_map.ads and libspe2_types.ads declare data types, data structures and constants used in libspe2 API. The libspe.ads defines all interfaces of libspe functions using Ada pragmas. To include the package files in Ada source file: with cbea_map.ads; with libspe_types.ads; with libspe.ads; Further more to have full visibility of the data and interfaces: use cbea_map.ads; use libspe_types.ads; use libspe.ads The Ada binding package files are installed under /usr/adainclude in SDK 3.0. You need to set this directory in your source path so that the compiler could find the packages. For instance in your GNAT project file hello.gpr: Project hello is for Source_Dirs use("/usr/adainclude/", "."); end hello; When compiling the Ada source program, add a GNAT option -Phello.gpr. e.g. ppu-gnatmake helloworld.adb -Phello.gpr The libspe2.ads file is linked with libspe dynamic library automatically through Linker_Options pragma. libspe2-2.2.80-95/ada/libspe2.ads0000644000175100017510000002022410644400150015544 0ustar arthurarthur----------------------------------------------------------- -- -- libspe2 API functions -- ----------------------------------------------------------- with System; with Interfaces.C; with libspe2_types; package libspe2 is use System; use Interfaces.C; use libspe2_types; -- -- link with libspe2 -- pragma Linker_Options("-lspe2"); -- -- spe_context_create -- function spe_context_create (flags : unsigned; gang : spe_gang_context_ptr_t) return spe_context_ptr_t; pragma Import (C, spe_context_create, "spe_context_create"); -- -- spe_context_create_affinity -- function spe_context_create_affinity (flags : unsigned; affinity_neighbor : spe_context_ptr_t; gang : spe_gang_context_ptr_t) return spe_context_ptr_t; pragma Import (C, spe_context_create_affinity, "spe_context_create_affinity"); -- -- spe_context_destroy -- function spe_context_destroy (spe : spe_context_ptr_t) return Integer; pragma Import (C, spe_context_destroy, "spe_context_destroy"); -- -- spe_gang_context_create -- function spe_gang_context_create (flags : unsigned) return spe_gang_context_ptr_t; pragma Import (C, spe_gang_context_create, "spe_gang_context_create"); -- -- spe_gang_context_destroy -- function spe_gang_context_destroy (gang : spe_gang_context_ptr_t) return Integer; pragma Import (C, spe_gang_context_destroy, "spe_gang_context_destroy"); -- -- spe_image_open -- function spe_image_open (filename : char_array) return spe_program_handle_t; pragma Import (C, spe_image_open, "spe_image_open"); -- -- spe_image_close -- function spe_image_close (program : spe_program_handle_t) return Integer; pragma Import (C, spe_image_close, "spe_image_close"); -- -- spe_program_load -- function spe_program_load (spe : spe_context_ptr_t; program : spe_program_handle_t) return Integer; pragma Import (C, spe_program_load, "spe_program_load"); -- -- spe_context_run -- function spe_context_run (spe : spe_context_ptr_t; spe_entry_ptr : access unsigned; run_flags : unsigned; argp : addr_ptr; envp : addr_ptr; stop_info : spe_stop_info_ptr) return Integer; pragma Import (C, spe_context_run, "spe_context_run"); -- -- spe_stop_info_read -- function spe_stop_info_read (spe : spe_context_ptr_t; stop_info : spe_stop_info_ptr) return Integer; pragma Import (C, spe_stop_info_read, "spe_stop_info_read"); -- -- spe_event_handler_create -- function spe_event_handler_create return spe_event_handler_ptr_t; pragma Import (C, spe_event_handler_create, "spe_event_handler_create"); -- -- spe_event_handler_destroy -- function spe_event_handler_destroy (evhandler :spe_event_handler_ptr_t) return Integer; pragma Import (C, spe_event_handler_destroy, "spe_event_handler_destroy"); -- -- spe_event_handler_register -- function spe_event_handler_register (evhandler : spe_event_handler_ptr_t; event : spe_event_unit_t_ptr) return Integer; pragma Import (C, spe_event_handler_register, "spe_event_handler_register"); -- -- spe_event_handler_deregister -- function spe_event_handler_deregister (evhandler : spe_event_handler_ptr_t; event : spe_event_unit_t_ptr) return Integer; pragma Import (C, spe_event_handler_deregister, "spe_event_handler_deregister"); -- -- spe_event_wait -- function spe_event_wait (evhandler : spe_event_handler_ptr_t; events : addr_ptr; max_events : Integer; timeout : Integer) return Integer; pragma Import (C, spe_event_wait, "spe_event_wait"); -- -- MFCIO Proxy Commands -- function spe_mfcio_put (spe : spe_context_ptr_t; ls : unsigned; ea : addr_ptr; size : unsigned; tag : unsigned; tid : unsigned; rid : unsigned) return Integer; pragma Import (C, spe_mfcio_put, "spe_mfcio_put"); function spe_mfcio_putb (spe : spe_context_ptr_t; ls : unsigned; ea : addr_ptr; size : unsigned; tag : unsigned; tid : unsigned; rid : unsigned) return Integer; pragma Import (C, spe_mfcio_putb, "spe_mfcio_putb"); function spe_mfcio_putf (spe : spe_context_ptr_t; ls : unsigned; ea : addr_ptr; size : unsigned; tag : unsigned; tid : unsigned; rid : unsigned) return Integer; pragma Import (C, spe_mfcio_putf, "spe_mfcio_putf"); function spe_mfcio_get (spe : spe_context_ptr_t; ls : unsigned; ea : addr_ptr; size : unsigned; tag : unsigned; tid : unsigned; rid : unsigned) return Integer; pragma Import (C, spe_mfcio_get, "spe_mfcio_get"); function spe_mfcio_getb (spe : spe_context_ptr_t; ls : unsigned; ea : addr_ptr; size : unsigned; tag : unsigned; tid : unsigned; rid : unsigned) return Integer; pragma Import (C, spe_mfcio_getb, "spe_mfcio_getb"); function spe_mfcio_getf (spe : spe_context_ptr_t; ls : unsigned; ea : addr_ptr; size : unsigned; tag : unsigned; tid : unsigned; rid : unsigned) return Integer; pragma Import (C, spe_mfcio_getf, "spe_mfcio_getf"); -- -- MFCIO Tag Group Completion -- function spe_mfcio_tag_status_read (spe : spe_context_ptr_t; mask : unsigned; behavior : unsigned; tag_status_ptr : unsigned_ptr) return Integer; pragma Import (C, spe_mfcio_tag_status_read, "spe_mfcio_tag_status_read"); -- -- SPE Mailbox Facility -- function spe_out_mbox_read (spe : spe_context_ptr_t; mbox_data_ptr : unsigned_ptr; count : Integer) return Integer; pragma Import (C, spe_out_mbox_read, "spe_out_mbox_read"); function spe_out_mbox_status (spe : spe_context_ptr_t) return Integer; pragma Import (C, spe_out_mbox_status, "spe_out_mbox_status"); function spe_in_mbox_write (spe : spe_context_ptr_t; mbox_data_ptr : unsigned_ptr; count : Integer; behavior : unsigned) return Integer; pragma Import (C, spe_in_mbox_write, "spe_in_mbox_write"); function spe_in_mbox_status (spe : spe_context_ptr_t) return Integer; pragma Import (C, spe_in_mbox_status, "spe_in_mbox_status"); function spe_out_intr_mbox_read (spe : spe_context_ptr_t; mbox_data_ptr : unsigned_ptr; count : Integer; behavior : unsigned) return Integer; pragma Import (C, spe_out_intr_mbox_read, "spe_out_intr_mbox_read"); function spe_out_intr_mbox_status (spe : spe_context_ptr_t) return Integer; pragma Import (C, spe_out_intr_mbox_status, "spe_out_intr_mbox_status"); -- -- SPU SIgnal Notification Facility -- function spe_signal_write (spe : spe_context_ptr_t; signal_reg : unsigned; data : unsigned) return Integer; pragma Import (C, spe_signal_write, "spe_signal_write"); -- -- spe_ls_area_get -- function spe_ls_area_get (spe : spe_context_ptr_t) return addr_ptr; pragma Import (C, spe_ls_area_get, "spe_ls_area_get"); -- -- spe_ls_size_get -- function spe_ls_size_get (spe : spe_context_ptr_t) return Integer; pragma Import (C, spe_ls_size_get, "spe_ls_size_get"); -- -- spe_ps_area_get -- function spe_ps_area_get (spe : spe_context_ptr_t; area : ps_area) return addr_ptr; pragma Import (C, spe_ps_area_get, "spe_ps_area_get"); -- -- spe_callback_handler_register -- function spe_callback_handler_register (handler : addr_ptr; callnum : unsigned; mode : unsigned) return Integer; pragma Import (C, spe_callback_handler_register, "spe_callback_handler_register"); -- -- spe_callback_handler_deregister -- function spe_callback_handler_deregister (callnum : unsigned) return Integer; pragma Import (C, spe_callback_handler_deregister, "spe_callback_handler_deregister"); -- -- spe_callback_handler_query -- function spe_callback_handler_query (callnum : unsigned) return spe_event_handler_ptr_t; pragma Import (C, spe_callback_handler_query, "spe_callback_handler_query"); -- -- spe_cpu_info_get -- function spe_cpu_info_get (info_requested : Integer; cpu_node : Integer) return Integer; pragma Import (C, spe_cpu_info_get, "spe_cpu_info_get"); end libspe2; libspe2-2.2.80-95/ada/cbea_map.ads0000644000175100017510000000354610643145366015761 0ustar arthurarthur-- -- Data structure declarations for SPE problem state areas -- (part of public API) -- with System; with Interfaces.C; package cbea_map is use System; use Interfaces.C; type spe_mssync_area_t is record MFC_MSSync : unsigned; end record; type spe_mssync_area_ptr is access spe_mssync_area_t; type spe_mfc_command_area_t is record reserved_0_3 : char_array (0 .. 3); MFC_LSA : unsigned; MFC_EAH : unsigned; MFC_EAL : unsigned; MFC_Size_Tag : unsigned; MFC_ClassID_CMD : unsigned; -- MFC_CMDStatus : unsigned; reserved_18_103 : char_array (0 .. 235); MFC_QStatus : unsigned; reserved_108_203 : char_array (0 .. 251); Prxy_QueryType : unsigned; reserved_208_21B : char_array (0 .. 19); Prxy_QueryMask : unsigned; reserved_220_22B : char_array (0 .. 11); Prxy_TagStatus : unsigned; end record; type spe_mfc_command_area_ptr is access spe_mfc_command_area_t; type spe_spu_control_area_t is record reserved_0_3 : char_array (0 .. 3); SPU_Out_Mbox : unsigned; reserved_8_B : char_array (0 .. 3); SPU_In_Mbox : unsigned; reserved_10_13 : char_array (0 .. 3); SPU_Mbox_Stat : unsigned; reserved_18_1B : char_array (0 .. 3); SPU_RunCntl : unsigned; reserved_20_23 : char_array (0 .. 3); SPU_Status : unsigned; reserved_28_33 : char_array (0 .. 11); SPU_NPC : unsigned; end record; type spe_spu_control_area_ptr is access spe_spu_control_area_t; type spe_sig_notify_1_area_t is record reserved_0_B : char_array (0 .. 11); SPU_Sig_Notify_1 : unsigned; end record; type spe_sig_notify_1_area_ptr is access spe_sig_notify_1_area_t; type spe_sig_notify_2_area_t is record reserved_0_B : char_array (0 .. 11); SPU_Sig_Notify_2 : unsigned; end record; type spe_sig_notify_2_area_ptr is access spe_sig_notify_2_area_t; end cbea_map; libspe2-2.2.80-95/PATCH-SUBMITTING-RULES0000644000175100017510000001147510606704104016137 0ustar arthurarthurHow to submit your patches against libspe * Contributing to the project In libspe project, only the project maintainers have write access to the repository and other developers are encouraged to contribute their changes to the project via patches posted to a mailing list. This document shows such contributors how to create and post their patches. * Creating patches Create your patches by the following rules: - Generate patches in the following format: - Use "diff -uprN" to generate patches. - The patches should be created one directory higher than the root source directory of libspe, i.e. the created patches should be applied by "patch -p1" in the root directory of libspe. e.g.) SHELL> tar xvfz libspe2-2.1.0.tar.gz SHELL> mv libspe2-2.1.0 libspe2-2.1.0.orig SHELL> diff -uprN libspe2-2.1.0.orig libspe2-2.1.0.mine > my.patch NOTE) The recent versions of Quilt generate patches in the required format by default. NOTE) Subversion and CVS can generate diffs in the required format as following: Subversion: svn diff --diff-cmd diff -x -up libspe2 CVS: cvs diff -upN libspe2 Some of the options above can be specified in your configuration files as default behaviors. See manuals for details. - Generate patches against the latest release or against the latest revision (or one of the recent revisions) in the public repository. NOTE) The public repository is available at "http://sourceforge.net/projects/libspe/". - Add explanation for your changes to the patches. - Sign the patches. Put your sign on the patches, if you can certify the below: Developer's Certificate of Origin 1.1 By making a contribution to this project, I certify that: (a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or (b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or (c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it. (d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved. To sign the patches, just put a line at the end of explanation for your patches as following: Signed-off-by: Your Name * Submitting patches Submit your patches according to the following rules: - Send the patches by e-mail to the "cbe-oss-dev@ozlabs.org" mailing list. NOTE) Visit "https://ozlabs.org/mailman/listinfo/cbe-oss-dev" to subscribe to the mailing list. - Put subject on the e-mail as following. Subject: [PATCH /] libspe2: "/" can be omitted if you submit just one patch at the same time. e.g.) Subject: [PATCH] libspe2: Fix foo Subject: [PATCH 1/2] libspe2: Fix bar * Example ------------------------------------------------------------------- To: cbe-oss-dev@ozlabs.org Subject: [PATCH] libspe2: Fix typo in debug print This patch fixes typo in debug print. Signed-off-by: Your Name ---- diff -uprN libspe2-2.1.0.orig/spebase/run.c libspe2-2.1.0.mine/spebase/run.c --- libspe2-2.1.0.orig/spebase/run.c 2007-03-08 17:42:42.000000000 +0900 +++ libspe2-2.1.0.mine/spebase/run.c 2007-04-04 23:01:03.000000000 +0900 @@ -265,7 +265,7 @@ int _base_spe_context_run(spe_context_pt return -1; } else if (ret & 0x08) { /*Test for wait on channel*/ // 0x08 SPU is waiting for a channel. - DEBUG_PRINTF("0x04 SPU is waiting on channel. %d\n", ret); + DEBUG_PRINTF("0x08 SPU is waiting on channel. %d\n", ret); stopinfo->stop_reason = SPE_RUNTIME_EXCEPTION; stopinfo->result.spe_runtime_exception = spu_extended_status; stopinfo->spu_status = -1; ------------------------------------------------------------------- --- EOF libspe2-2.2.80-95/speevent/0000755000175100017510000000000010707604274014634 5ustar arthurarthurlibspe2-2.2.80-95/speevent/spe_event.c0000644000175100017510000002650110640341732016765 0ustar arthurarthur/* * libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS * * Copyright (C) 2006 Sony Computer Entertainment Inc. * Copyright 2006 Sony Corp. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "speevent.h" #include #include #include #include #include #define __SPE_EVENT_ALL \ ( SPE_EVENT_OUT_INTR_MBOX | SPE_EVENT_IN_MBOX | \ SPE_EVENT_TAG_GROUP | SPE_EVENT_SPE_STOPPED ) #define __SPE_EPOLL_SIZE 10 #define __SPE_EPOLL_FD_GET(handler) (*(int*)(handler)) #define __SPE_EPOLL_FD_SET(handler, fd) (*(int*)(handler) = (fd)) #define __SPE_EVENT_CONTEXT_PRIV_GET(spe) \ ( (spe_context_event_priv_ptr_t)(spe)->event_private) #define __SPE_EVENT_CONTEXT_PRIV_SET(spe, evctx) \ ( (spe)->event_private = (evctx) ) #define __SPE_EVENTS_ENABLED(spe) \ ((spe)->base_private->flags & SPE_EVENTS_ENABLE) void _event_spe_context_lock(spe_context_ptr_t spe) { pthread_mutex_lock(&__SPE_EVENT_CONTEXT_PRIV_GET(spe)->lock); } void _event_spe_context_unlock(spe_context_ptr_t spe) { pthread_mutex_unlock(&__SPE_EVENT_CONTEXT_PRIV_GET(spe)->lock); } int _event_spe_stop_info_read (spe_context_ptr_t spe, spe_stop_info_t *stopinfo) { spe_context_event_priv_ptr_t evctx; int rc; int fd; size_t total; evctx = __SPE_EVENT_CONTEXT_PRIV_GET(spe); fd = evctx->stop_event_pipe[0]; pthread_mutex_lock(&evctx->stop_event_read_lock); /* for atomic read */ rc = read(fd, stopinfo, sizeof(*stopinfo)); if (rc == -1) { pthread_mutex_unlock(&evctx->stop_event_read_lock); return -1; } total = rc; while (total < sizeof(*stopinfo)) { /* this loop will be executed in few cases */ struct pollfd fds; fds.fd = fd; fds.events = POLLIN; rc = poll(&fds, 1, -1); if (rc == -1) { if (errno != EINTR) { break; } } else if (rc == 1) { rc = read(fd, (char *)stopinfo + total, sizeof(*stopinfo) - total); if (rc == -1) { if (errno != EAGAIN) { break; } } else { total += rc; } } } pthread_mutex_unlock(&evctx->stop_event_read_lock); return rc == -1 ? -1 : 0; } /* * spe_event_handler_create */ spe_event_handler_ptr_t _event_spe_event_handler_create(void) { int epfd; spe_event_handler_t *evhandler; evhandler = calloc(1, sizeof(*evhandler)); if (!evhandler) { return NULL; } epfd = epoll_create(__SPE_EPOLL_SIZE); if (epfd == -1) { free(evhandler); return NULL; } __SPE_EPOLL_FD_SET(evhandler, epfd); return evhandler; } /* * spe_event_handler_destroy */ int _event_spe_event_handler_destroy (spe_event_handler_ptr_t evhandler) { int epfd; if (!evhandler) { errno = ESRCH; return -1; } epfd = __SPE_EPOLL_FD_GET(evhandler); close(epfd); free(evhandler); return 0; } /* * spe_event_handler_register */ int _event_spe_event_handler_register(spe_event_handler_ptr_t evhandler, spe_event_unit_t *event) { int epfd; const int ep_op = EPOLL_CTL_ADD; spe_context_event_priv_ptr_t evctx; spe_event_unit_t *ev_buf; struct epoll_event ep_event; int fd; if (!evhandler) { errno = ESRCH; return -1; } if (!event || !event->spe) { errno = EINVAL; return -1; } if (!__SPE_EVENTS_ENABLED(event->spe)) { errno = ENOTSUP; return -1; } epfd = __SPE_EPOLL_FD_GET(evhandler); evctx = __SPE_EVENT_CONTEXT_PRIV_GET(event->spe); if (event->events & ~__SPE_EVENT_ALL) { errno = ENOTSUP; return -1; } _event_spe_context_lock(event->spe); /* for spe->event_private->events */ if (event->events & SPE_EVENT_OUT_INTR_MBOX) { fd = __base_spe_event_source_acquire(event->spe, FD_IBOX); if (fd == -1) { _event_spe_context_unlock(event->spe); return -1; } ev_buf = &evctx->events[__SPE_EVENT_OUT_INTR_MBOX]; ev_buf->events = SPE_EVENT_OUT_INTR_MBOX; ev_buf->data = event->data; ep_event.events = EPOLLIN; ep_event.data.ptr = ev_buf; if (epoll_ctl(epfd, ep_op, fd, &ep_event) == -1) { _event_spe_context_unlock(event->spe); return -1; } } if (event->events & SPE_EVENT_IN_MBOX) { fd = __base_spe_event_source_acquire(event->spe, FD_WBOX); if (fd == -1) { _event_spe_context_unlock(event->spe); return -1; } ev_buf = &evctx->events[__SPE_EVENT_IN_MBOX]; ev_buf->events = SPE_EVENT_IN_MBOX; ev_buf->data = event->data; ep_event.events = EPOLLOUT; ep_event.data.ptr = ev_buf; if (epoll_ctl(epfd, ep_op, fd, &ep_event) == -1) { _event_spe_context_unlock(event->spe); return -1; } } if (event->events & SPE_EVENT_TAG_GROUP) { fd = __base_spe_event_source_acquire(event->spe, FD_MFC); if (fd == -1) { _event_spe_context_unlock(event->spe); return -1; } if (event->spe->base_private->flags & SPE_MAP_PS) { _event_spe_context_unlock(event->spe); errno = ENOTSUP; return -1; } ev_buf = &evctx->events[__SPE_EVENT_TAG_GROUP]; ev_buf->events = SPE_EVENT_TAG_GROUP; ev_buf->data = event->data; ep_event.events = EPOLLIN; ep_event.data.ptr = ev_buf; if (epoll_ctl(epfd, ep_op, fd, &ep_event) == -1) { _event_spe_context_unlock(event->spe); return -1; } } if (event->events & SPE_EVENT_SPE_STOPPED) { fd = evctx->stop_event_pipe[0]; ev_buf = &evctx->events[__SPE_EVENT_SPE_STOPPED]; ev_buf->events = SPE_EVENT_SPE_STOPPED; ev_buf->data = event->data; ep_event.events = EPOLLIN; ep_event.data.ptr = ev_buf; if (epoll_ctl(epfd, ep_op, fd, &ep_event) == -1) { _event_spe_context_unlock(event->spe); return -1; } } _event_spe_context_unlock(event->spe); return 0; } /* * spe_event_handler_deregister */ int _event_spe_event_handler_deregister(spe_event_handler_ptr_t evhandler, spe_event_unit_t *event) { int epfd; const int ep_op = EPOLL_CTL_DEL; spe_context_event_priv_ptr_t evctx; int fd; if (!evhandler) { errno = ESRCH; return -1; } if (!event || !event->spe) { errno = EINVAL; return -1; } if (!__SPE_EVENTS_ENABLED(event->spe)) { errno = ENOTSUP; return -1; } epfd = __SPE_EPOLL_FD_GET(evhandler); evctx = __SPE_EVENT_CONTEXT_PRIV_GET(event->spe); if (event->events & ~__SPE_EVENT_ALL) { errno = ENOTSUP; return -1; } _event_spe_context_lock(event->spe); /* for spe->event_private->events */ if (event->events & SPE_EVENT_OUT_INTR_MBOX) { fd = __base_spe_event_source_acquire(event->spe, FD_IBOX); if (fd == -1) { _event_spe_context_unlock(event->spe); return -1; } if (epoll_ctl(epfd, ep_op, fd, NULL) == -1) { _event_spe_context_unlock(event->spe); return -1; } evctx->events[__SPE_EVENT_OUT_INTR_MBOX].events = 0; } if (event->events & SPE_EVENT_IN_MBOX) { fd = __base_spe_event_source_acquire(event->spe, FD_WBOX); if (fd == -1) { _event_spe_context_unlock(event->spe); return -1; } if (epoll_ctl(epfd, ep_op, fd, NULL) == -1) { _event_spe_context_unlock(event->spe); return -1; } evctx->events[__SPE_EVENT_IN_MBOX].events = 0; } if (event->events & SPE_EVENT_TAG_GROUP) { fd = __base_spe_event_source_acquire(event->spe, FD_MFC); if (fd == -1) { _event_spe_context_unlock(event->spe); return -1; } if (epoll_ctl(epfd, ep_op, fd, NULL) == -1) { _event_spe_context_unlock(event->spe); return -1; } evctx->events[__SPE_EVENT_TAG_GROUP].events = 0; } if (event->events & SPE_EVENT_SPE_STOPPED) { fd = evctx->stop_event_pipe[0]; if (epoll_ctl(epfd, ep_op, fd, NULL) == -1) { _event_spe_context_unlock(event->spe); return -1; } evctx->events[__SPE_EVENT_SPE_STOPPED].events = 0; } _event_spe_context_unlock(event->spe); return 0; } /* * spe_event_wait */ int _event_spe_event_wait(spe_event_handler_ptr_t evhandler, spe_event_unit_t *events, int max_events, int timeout) { int epfd; struct epoll_event *ep_events; int rc; if (!evhandler) { errno = ESRCH; return -1; } if (!events || max_events <= 0) { errno = EINVAL; return -1; } epfd = __SPE_EPOLL_FD_GET(evhandler); ep_events = malloc(sizeof(*ep_events) * max_events); if (!ep_events) { return -1; } for ( ; ; ) { rc = epoll_wait(epfd, ep_events, max_events, timeout); if (rc == -1) { /* error */ if (errno == EINTR) { if (timeout >= 0) { /* behave as timeout */ rc = 0; break; } /* else retry */ } else { break; } } else if (rc > 0) { int i; for (i = 0; i < rc; i++) { spe_event_unit_t *ev = (spe_event_unit_t *)(ep_events[i].data.ptr); _event_spe_context_lock(ev->spe); /* lock ev itself */ events[i] = *ev; _event_spe_context_unlock(ev->spe); } break; } else { /* timeout */ break; } } free(ep_events); return rc; } int _event_spe_context_finalize(spe_context_ptr_t spe) { spe_context_event_priv_ptr_t evctx; if (!spe) { errno = ESRCH; return -1; } evctx = __SPE_EVENT_CONTEXT_PRIV_GET(spe); __SPE_EVENT_CONTEXT_PRIV_SET(spe, NULL); close(evctx->stop_event_pipe[0]); close(evctx->stop_event_pipe[1]); pthread_mutex_destroy(&evctx->lock); pthread_mutex_destroy(&evctx->stop_event_read_lock); free(evctx); return 0; } struct spe_context_event_priv * _event_spe_context_initialize(spe_context_ptr_t spe) { spe_context_event_priv_ptr_t evctx; int rc; int i; evctx = calloc(1, sizeof(*evctx)); if (!evctx) { return NULL; } rc = pipe(evctx->stop_event_pipe); if (rc == -1) { free(evctx); return NULL; } rc = fcntl(evctx->stop_event_pipe[0], F_GETFL); if (rc != -1) { rc = fcntl(evctx->stop_event_pipe[0], F_SETFL, rc | O_NONBLOCK); } if (rc == -1) { close(evctx->stop_event_pipe[0]); close(evctx->stop_event_pipe[1]); free(evctx); errno = EIO; return NULL; } for (i = 0; i < sizeof(evctx->events) / sizeof(evctx->events[0]); i++) { evctx->events[i].spe = spe; } pthread_mutex_init(&evctx->lock, NULL); pthread_mutex_init(&evctx->stop_event_read_lock, NULL); return evctx; } int _event_spe_context_run (spe_context_ptr_t spe, unsigned int *entry, unsigned int runflags, void *argp, void *envp, spe_stop_info_t *stopinfo) { spe_context_event_priv_ptr_t evctx; spe_stop_info_t stopinfo_buf; int rc; if (!stopinfo) { stopinfo = &stopinfo_buf; } rc = _base_spe_context_run(spe, entry, runflags, argp, envp, stopinfo); evctx = __SPE_EVENT_CONTEXT_PRIV_GET(spe); if (write(evctx->stop_event_pipe[1], stopinfo, sizeof(*stopinfo)) != sizeof(*stopinfo)) { /* error check. */ } return rc; } libspe2-2.2.80-95/speevent/speevent.h0000644000175100017510000000473310610601440016626 0ustar arthurarthur/* * libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _SPEEVENT_H_ #define _SPEEVENT_H_ #include "spebase.h" /* private constants */ enum __spe_event_types { __SPE_EVENT_OUT_INTR_MBOX, __SPE_EVENT_IN_MBOX, __SPE_EVENT_TAG_GROUP, __SPE_EVENT_SPE_STOPPED, __NUM_SPE_EVENT_TYPES }; /* private types */ typedef struct spe_context_event_priv { pthread_mutex_t lock; pthread_mutex_t stop_event_read_lock; int stop_event_pipe[2]; spe_event_unit_t events[__NUM_SPE_EVENT_TYPES]; } spe_context_event_priv_t, *spe_context_event_priv_ptr_t; int _event_spe_stop_info_read (spe_context_ptr_t spe, spe_stop_info_t *stopinfo); /* * spe_event_handler_create */ spe_event_handler_ptr_t _event_spe_event_handler_create(void); /* * spe_event_handler_destroy */ int _event_spe_event_handler_destroy (spe_event_handler_ptr_t evhandler); /* * spe_event_handler_register */ int _event_spe_event_handler_register(spe_event_handler_ptr_t evhandler, spe_event_unit_t *event); /* * spe_event_handler_deregister */ int _event_spe_event_handler_deregister(spe_event_handler_ptr_t evhandler, spe_event_unit_t *event); /* * spe_event_wait */ int _event_spe_event_wait(spe_event_handler_ptr_t evhandler, spe_event_unit_t *events, int max_events, int timeout); int _event_spe_context_finalize(spe_context_ptr_t spe); struct spe_context_event_priv * _event_spe_context_initialize(spe_context_ptr_t spe); int _event_spe_context_run (spe_context_ptr_t spe, unsigned int *entry, unsigned int runflags, void *argp, void *envp, spe_stop_info_t *stopinfo); void _event_spe_context_lock(spe_context_ptr_t spe); void _event_spe_context_unlock(spe_context_ptr_t spe); #endif /*SPEEVENT_H_*/ libspe2-2.2.80-95/speevent/Makefile0000644000175100017510000000324210603065010016255 0ustar arthurarthur#* #* libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS #* #* This library is free software; you can redistribute it and/or modify it #* under the terms of the GNU Lesser General Public License as published by #* the Free Software Foundation; either version 2.1 of the License, #* or (at your option) any later version. #* #* This library is distributed in the hope that it will be useful, but #* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY #* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public #* License for more details. #* #* You should have received a copy of the GNU Lesser General Public License #* along with this library; if not, write to the Free Software Foundation, #* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #* TOP=.. include $(TOP)/make.defines MAJOR_VERSION := 2 MINOR_VERSION := 0.0 libspeevent_A := libspeevent.a libspeevent_SO := libspeevent.so.${MAJOR_VERSION}.${MINOR_VERSION} libspeevent_SONAME := libspeevent.so.${MAJOR_VERSION} libspeevent_OBJS := spe_event.o CFLAGS += -I$(TOP)/spebase CFLAGS += -I$(TOP) all: $(libspeevent_SO) $(libspeevent_A) install-so: $(libspeevent_SO) $(libspeevent_A) $(INSTALL_DIR) $(ROOT)$(includedir) $(INSTALL_DATA) speevent.h $(ROOT)$(includedir)/speevent.h $(INSTALL_DIR) $(ROOT)$(speinclude) clean: rm -f $(libspeevent_OBJS) rm -f $(libspeevent_SO) rm -f libspeevent.a $(libspeevent_SO): $(libspeevent_OBJS) $(CC) $(CFLAGS) -shared -o $@ $^ -lrt -lpthread -Wl,--soname=${libspeevent_SONAME} $(libspeevent_A): $(libspeevent_OBJS) $(CROSS)ar -r $(libspeevent_A) $(libspeevent_OBJS) ../spebase/*.o libspe2-2.2.80-95/libspe2.c0000644000175100017510000002407210647137613014515 0ustar arthurarthur/* * SPE Runtime Management Library, Version 2.0 * This library constitutes the standardized low-level application * programming interface for application access to the Cell Broadband * Engineís Synergistic Processing Elements (SPEs). * * The usage of this library requires that the application programmer * is familiar with the CBE architecture as described in ìCell * Broadband Engine Architecture, Version 1.0î. * * Copyright (C) 2006 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * libspe2.ch contains the implementation of public API funtions */ #include "libspe2.h" #include "spebase.h" #include "speevent.h" /* * spe_context_create */ spe_context_ptr_t spe_context_create(unsigned int flags, spe_gang_context_ptr_t gang) { spe_context_ptr_t spe = _base_spe_context_create(flags, gang, NULL); if ( spe == NULL ) { return NULL; } else { if ( flags & SPE_EVENTS_ENABLE ) { /* initialize event handling */ spe->event_private = _event_spe_context_initialize(spe); if ( spe->event_private == NULL ) { /* error initializing event handling */ _base_spe_context_destroy(spe); return NULL; } } else { spe->event_private = NULL; } } return spe; } /* * spe_context_create_affinity */ spe_context_ptr_t spe_context_create_affinity(unsigned int flags, spe_context_ptr_t affinity_neighbor, spe_gang_context_ptr_t gang) { spe_context_ptr_t spe = _base_spe_context_create(flags, gang, affinity_neighbor); if ( spe == NULL ) { return NULL; } else { if ( flags & SPE_EVENTS_ENABLE ) { /* initialize event handling */ spe->event_private = _event_spe_context_initialize(spe); if ( spe->event_private == NULL ) { /* error initializing event handling */ _base_spe_context_destroy(spe); return NULL; } } else { spe->event_private = NULL; } } return spe; } /* * spe_context_destroy */ int spe_context_destroy (spe_context_ptr_t spe) { if (spe == NULL ) { errno = ESRCH; return -1; } if ( spe->event_private != NULL ) { int ret = _event_spe_context_finalize(spe); if (ret) { /* error releasing event-related resources */ return ret; } } return _base_spe_context_destroy(spe); } /* * spe_gang_context_create */ spe_gang_context_ptr_t spe_gang_context_create (unsigned int flags) { return _base_spe_gang_context_create(flags); } /* * spe_gang_context_destroy */ int spe_gang_context_destroy (spe_gang_context_ptr_t gang) { if (gang == NULL ) { errno = ESRCH; return -1; } return _base_spe_gang_context_destroy (gang); } /* * spe_image_open */ spe_program_handle_t * spe_image_open (const char *filename) { return _base_spe_image_open(filename); } /* * spe_image_close */ int spe_image_close (spe_program_handle_t *program) { return _base_spe_image_close(program); } /* * spe_load_program */ int spe_program_load (spe_context_ptr_t spe, spe_program_handle_t *program) { if (spe == NULL ) { errno = ESRCH; return -1; } if (program == NULL ) { errno = EINVAL; return -1; } return _base_spe_program_load(spe, program); } /* * spe_context_run */ int spe_context_run (spe_context_ptr_t spe, unsigned int *entry, unsigned int runflags, void *argp, void *envp, spe_stop_info_t *stopinfo) { if (spe == NULL ) { errno = ESRCH; return -1; } if ( spe->event_private != NULL ) { return _event_spe_context_run(spe, entry, runflags, argp, envp, stopinfo); } else { return _base_spe_context_run(spe, entry, runflags, argp, envp, stopinfo); } } /* * spe_stop_info_read */ int spe_stop_info_read (spe_context_ptr_t spe, spe_stop_info_t *stopinfo) { if (spe == NULL ) { errno = ESRCH; return -1; } if (spe->event_private == NULL) { errno = ENOTSUP; return -1; } else { return _event_spe_stop_info_read (spe, stopinfo); } } /* * spe_event_handler_create */ spe_event_handler_ptr_t spe_event_handler_create(void) { return _event_spe_event_handler_create(); } /* * spe_event_handler_destroy */ int spe_event_handler_destroy (spe_event_handler_ptr_t evhandler) { return _event_spe_event_handler_destroy(evhandler); } /* * spe_event_handler_register */ int spe_event_handler_register(spe_event_handler_ptr_t evhandler, spe_event_unit_t *event) { return _event_spe_event_handler_register(evhandler, event); } /* * spe_event_handler_deregister */ int spe_event_handler_deregister(spe_event_handler_ptr_t evhandler, spe_event_unit_t *event) { return _event_spe_event_handler_deregister(evhandler, event); } /* * spe_event_wait */ int spe_event_wait(spe_event_handler_ptr_t evhandler, spe_event_unit_t *events, int max_events, int timeout) { return _event_spe_event_wait(evhandler, events, max_events, timeout); } /* * MFCIO Proxy Commands */ int spe_mfcio_put (spe_context_ptr_t spe, unsigned int ls, void *ea, unsigned int size, unsigned int tag, unsigned int tid, unsigned int rid) { if (spe == NULL ) { errno = ESRCH; return -1; } return _base_spe_mfcio_put(spe, ls, ea, size, tag, tid, rid); } int spe_mfcio_putb (spe_context_ptr_t spe, unsigned int ls, void *ea, unsigned int size, unsigned int tag, unsigned int tid, unsigned int rid) { if (spe == NULL ) { errno = ESRCH; return -1; } return _base_spe_mfcio_putb(spe, ls, ea, size, tag, tid, rid); } int spe_mfcio_putf (spe_context_ptr_t spe, unsigned int ls, void *ea, unsigned int size, unsigned int tag, unsigned int tid, unsigned int rid) { if (spe == NULL ) { errno = ESRCH; return -1; } return _base_spe_mfcio_putf(spe, ls, ea, size, tag, tid, rid); } int spe_mfcio_get (spe_context_ptr_t spe, unsigned int ls, void *ea, unsigned int size, unsigned int tag, unsigned int tid, unsigned int rid) { if (spe == NULL ) { errno = ESRCH; return -1; } return _base_spe_mfcio_get(spe, ls, ea, size, tag, tid, rid); } int spe_mfcio_getb (spe_context_ptr_t spe, unsigned int ls, void *ea, unsigned int size, unsigned int tag, unsigned int tid, unsigned int rid) { if (spe == NULL ) { errno = ESRCH; return -1; } return _base_spe_mfcio_getb(spe, ls, ea, size, tag, tid, rid); } int spe_mfcio_getf (spe_context_ptr_t spe, unsigned int ls, void *ea, unsigned int size, unsigned int tag, unsigned int tid, unsigned int rid) { if (spe == NULL ) { errno = ESRCH; return -1; } return _base_spe_mfcio_getf(spe, ls, ea, size, tag, tid, rid); } /* * MFCIO Tag Group Completion */ int spe_mfcio_tag_status_read(spe_context_ptr_t spe, unsigned int mask, unsigned int behavior, unsigned int *tag_status) { if (spe == NULL ) { errno = ESRCH; return -1; } return _base_spe_mfcio_tag_status_read(spe, mask, behavior, tag_status); } /* * SPE Mailbox Facility */ int spe_out_mbox_read (spe_context_ptr_t spe, unsigned int *mbox_data, int count) { if (spe == NULL ) { errno = ESRCH; return -1; } return _base_spe_out_mbox_read(spe, mbox_data, count); } int spe_out_mbox_status (spe_context_ptr_t spe) { if (spe == NULL ) { errno = ESRCH; return -1; } return _base_spe_out_mbox_status(spe); } int spe_in_mbox_write (spe_context_ptr_t spe, unsigned int *mbox_data, int count, unsigned int behavior) { if (spe == NULL ) { errno = ESRCH; return -1; } return _base_spe_in_mbox_write(spe, mbox_data, count, behavior); } int spe_in_mbox_status (spe_context_ptr_t spe) { if (spe == NULL ) { errno = ESRCH; return -1; } return _base_spe_in_mbox_status(spe); } int spe_out_intr_mbox_read (spe_context_ptr_t spe, unsigned int *mbox_data, int count, unsigned int behavior) { if (spe == NULL ) { errno = ESRCH; return -1; } return _base_spe_out_intr_mbox_read(spe, mbox_data, count, behavior); } int spe_out_intr_mbox_status (spe_context_ptr_t spe) { if (spe == NULL ) { errno = ESRCH; return -1; } return _base_spe_out_intr_mbox_status(spe); } /* * Multisource Sync Facility */ int spe_mssync_start(spe_context_ptr_t spe) { if (spe == NULL ) { errno = ESRCH; return -1; } return _base_spe_mssync_start(spe); } int spe_mssync_status(spe_context_ptr_t spe) { if (spe == NULL ) { errno = ESRCH; return -1; } return _base_spe_mssync_status(spe); } /* * SPU SIgnal Notification Facility */ int spe_signal_write (spe_context_ptr_t spe, unsigned int signal_reg, unsigned int data) { if (spe == NULL ) { errno = ESRCH; return -1; } return _base_spe_signal_write(spe, signal_reg, data); } /* * spe_ls_area_get */ void * spe_ls_area_get (spe_context_ptr_t spe) { if (spe == NULL ) { errno = ESRCH; return NULL; } return _base_spe_ls_area_get (spe); } /* * spe_ls_size_get */ int spe_ls_size_get (spe_context_ptr_t spe) { if (spe == NULL ) { errno = ESRCH; return -1; } return _base_spe_ls_size_get(spe); } /* * spe_ps_area_get */ void * spe_ps_area_get (spe_context_ptr_t spe, enum ps_area area) { if (spe == NULL ) { errno = ESRCH; return NULL; } return _base_spe_ps_area_get(spe, area); } /* * spe_callback_handler_register */ int spe_callback_handler_register (void *handler, unsigned int callnum, unsigned int mode) { return _base_spe_callback_handler_register(handler, callnum, mode); } /* * spe_callback_handler_deregister */ int spe_callback_handler_deregister (unsigned int callnum) { return _base_spe_callback_handler_deregister(callnum); } /* * spe_callback_handler_query */ void * spe_callback_handler_query(unsigned int callnum) { return _base_spe_callback_handler_query(callnum); } /* * spe_info_get */ int spe_cpu_info_get(int info_requested, int cpu_node) { return _base_spe_cpu_info_get(info_requested, cpu_node); } #ifdef __cplusplus } #endif libspe2-2.2.80-95/libspe12/0000755000175100017510000000000010707604273014423 5ustar arthurarthurlibspe2-2.2.80-95/libspe12/tests/0000755000175100017510000000000010707604273015565 5ustar arthurarthurlibspe2-2.2.80-95/libspe12/tests/elfspe/0000755000175100017510000000000010707604273017043 5ustar arthurarthurlibspe2-2.2.80-95/libspe12/tests/elfspe/Makefile0000644000175100017510000000241310600243027020467 0ustar arthurarthur#* #* libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS #* Copyright (C) 2005 IBM Corp. #* #* This library is free software; you can redistribute it and/or modify it #* under the terms of the GNU Lesser General Public License as published by #* the Free Software Foundation; either version 2.1 of the License, #* or (at your option) any later version. #* #* This library is distributed in the hope that it will be useful, but #* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY #* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public #* License for more details. #* #* You should have received a copy of the GNU Lesser General Public License #* along with this library; if not, write to the Free Software Foundation, #* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #* CC := gcc SPECC := spu-gcc CFLAGS := -O2 -Wall -I../.. -I../../include -g SPECFLAGS := -O2 -Wall -I../../include SPELDFLAGS := -L/usr/spu/lib LIBS := -L../.. -lspe -lpthread SPELIBS := -lc -lgloss SPE_OBJS := spe-helloworld OBJS := runspe all: $(SPE_OBJS) $(OBJS) clean: rm -f $(SPE_OBJS) $(OBJS) $(SPE_OBJS): %: %.c $(SPECC) $(SPECFLAGS) $(SPELDFLAGS) -o $@ $< $(SPELIBS) $(OBJS): %: %.c $(CC) $(CFLAGS) -o $@ $< $(LIBS) libspe2-2.2.80-95/libspe12/tests/elfspe/runtest.sh0000755000175100017510000000015210600243027021070 0ustar arthurarthur#!/bin/bash echo Registering elfspe. ../../elfspe-register echo Running spe-helloworld. ./spe-helloworld libspe2-2.2.80-95/libspe12/tests/elfspe/runspe.c0000644000175100017510000000320710600243027020511 0ustar arthurarthur/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include int main(int argc, char* argv[]) { spe_program_handle_t *binary; speid_t spe_thread; spe_gid_t spe_group; int max_spe, status; if (argc != 2) { printf("usage: pu spu-executable\n"); exit(1); } binary = spe_open_image(argv[1]); if (!binary) exit(2); spe_group = spe_create_group(SCHED_OTHER, 0, 0); if (!spe_group) { printf("error: create_group.\n"); } max_spe = spe_group_max(spe_group); printf("info: group_max=%i\n", max_spe); spe_thread = spe_create_thread(spe_group, binary, NULL, NULL, 0, 0); if (spe_thread) { spe_wait(spe_thread, &status,0); printf("Thread returned status: %04x\n",status); } else perror("Could not create thread"); spe_close_image(binary); return 0; } libspe2-2.2.80-95/libspe12/tests/elfspe/spe-helloworld.c0000644000175100017510000000011110600243027022124 0ustar arthurarthur#include int main() { printf("Hello World.\n"); return 0; } libspe2-2.2.80-95/libspe12/tests/event/0000755000175100017510000000000010707604273016706 5ustar arthurarthurlibspe2-2.2.80-95/libspe12/tests/event/Makefile0000644000175100017510000000240310600243027020331 0ustar arthurarthur#* #* libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS #* Copyright (C) 2005 IBM Corp. #* #* This library is free software; you can redistribute it and/or modify it #* under the terms of the GNU Lesser General Public License as published by #* the Free Software Foundation; either version 2.1 of the License, #* or (at your option) any later version. #* #* This library is distributed in the hope that it will be useful, but #* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY #* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public #* License for more details. #* #* You should have received a copy of the GNU Lesser General Public License #* along with this library; if not, write to the Free Software Foundation, #* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #* CC := gcc SPECC := spu-gcc CTAGS = ctags CFLAGS := -O2 -m32 -Wall -g -I../.. SPECFLAGS := -O2 -Wall LDFLAGS := -m32 LIBS := -L ../.. -lspe -lpthread SPE_OBJS := spe-start-stop OBJS := ppe-start-stop all: $(OBJS) $(SPE_OBJS) clean: rm -f $(OBJS) $(SPE_OBJS) ppe-start-stop: ppe-start-stop.c ../../libspe.a $(CC) -o $@ $< $(CFLAGS) $(LDFLAGS) $(LIBS) spe-start-stop: spe-start-stop.c $(SPECC) $(SPECFLAGS) -o $@ $< libspe2-2.2.80-95/libspe12/tests/event/spe-start-stop.c0000644000175100017510000000244510600243027021750 0ustar arthurarthur/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include int main(void) { int i,j,a[128]; for(i=0; i< 1500000 ; i++) { for(j=0; j< 128; j++) { a[j] += i; } } si_stop(0x1199); for(i=0; i< 1500000 ; i++) { for(j=0; j< 128; j++) { a[j] += i; } } // spu_writech(mfc_wr_intr_mailbox, 0xaabd); spu_writech(SPU_WrOutIntrMbox, 0xaabd); for(i=0; i< 1500000 ; i++) { for(j=0; j< 128; j++) { a[j] += i; } } si_stop(0x119A); return 0; } libspe2-2.2.80-95/libspe12/tests/event/ppe-start-stop.c0000644000175100017510000000652010600243027021743 0ustar arthurarthur/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include int main(int argc, char* argv[]) { spe_program_handle_t *binary,*binary1; speid_t spe_thread,spe_thread1; spe_gid_t spe_group; int max_spe, status; int numthread = 2; if (argc != 2) { printf("usage: pu spu-executable\n"); exit(1); } binary = spe_open_image(argv[1]); if (!binary) exit(2); binary1 = spe_open_image(argv[1]); if (!binary1) exit(2); spe_group = spe_create_group(SCHED_OTHER, 0, 1); if (!spe_group) { printf("error: create_group.\n"); } max_spe = spe_group_max(spe_group); printf("info: group_max=%i\n", max_spe); spe_thread = spe_create_thread(spe_group, binary, NULL, NULL, 0, 0); usleep(500000); spe_thread1 = spe_create_thread(spe_group, binary, NULL, NULL, 0, 0); if (!spe_thread) { perror("Could not create thread"); return -1; } while (1==1) { struct spe_event myevent; int ret; myevent.gid = spe_group; myevent.events = SPE_EVENT_STOP | SPE_EVENT_THREAD_EXIT ; ret = spe_get_event( &myevent,1, 100); if (!ret) { printf("get_event: timeout\n"); } else { printf("get_event: revents=0x%04x\n",myevent.revents); printf("get_event: data=0x%04lx\n",myevent.data); printf("get_event: speid=%p\n",myevent.speid); spe_kill(myevent.speid,SIGCONT); if (myevent.data == 0x1199) { break; } } } usleep(200000); while (1==1) { struct spe_event myevent[2]; int ret; myevent[0].gid = spe_group; myevent[0].events = SPE_EVENT_STOP | SPE_EVENT_THREAD_EXIT; myevent[1].gid = spe_group; myevent[1].events = SPE_EVENT_MAILBOX; ret = spe_get_event(&myevent[0], 2, 100); if (!ret) { printf("get_event: timeout\n"); } else { printf("get_event: Got %i events.\n",ret); printf("get_event[0]: revents=0x%04x\n",myevent[0].revents); printf("get_event[0]: data=0x%04lx\n",myevent[0].data); printf("get_event[0]: speid=%p\n",myevent[0].speid); printf("get_event[1]: revents=0x%04x\n",myevent[1].revents); printf("get_event[1]: data=0x%04lx\n",myevent[1].data); printf("get_event[1]: speid=%p\n",myevent[1].speid); if (myevent[0].revents == SPE_EVENT_STOP) spe_kill(myevent[0].speid,SIGCONT); if (myevent[0].revents == SPE_EVENT_THREAD_EXIT) { spe_wait(myevent[0].speid, &status,0); numthread--; if (!numthread) break; } } } spe_close_image(binary); spe_close_image(binary1); return 0; } libspe2-2.2.80-95/libspe12/tests/dma/0000755000175100017510000000000010707604273016326 5ustar arthurarthurlibspe2-2.2.80-95/libspe12/tests/dma/Makefile0000644000175100017510000000253710600243027017761 0ustar arthurarthur#* #* libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS #* Copyright (C) 2005 IBM Corp. #* #* This library is free software; you can redistribute it and/or modify it #* under the terms of the GNU Lesser General Public License as published by #* the Free Software Foundation; either version 2.1 of the License, #* or (at your option) any later version. #* #* This library is distributed in the hope that it will be useful, but #* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY #* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public #* License for more details. #* #* You should have received a copy of the GNU Lesser General Public License #* along with this library; if not, write to the Free Software Foundation, #* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #* CC := gcc SPECC := spu-gcc CTAGS = ctags CFLAGS := -O2 -m32 -Wall -I../.. -I../../include -g SPECFLAGS := -O2 -Wall -I../../include -Wno-main LDFLAGS := -m32 LIBS := -L../.. -lspe -lpthread SPE_OBJS := spe-dma-read spe-dma-write OBJS := ppe-dma-test all: $(OBJS) $(SPE_OBJS) clean: rm -f $(OBJS) $(SPE_OBJS) ppe-dma-test: ppe-dma-test.c $(CC) -o $@ $< $(CFLAGS) $(LDFLAGS) $(LIBS) spe-dma-read: spe-dma-read.c $(SPECC) $(SPECFLAGS) -o $@ $< spe-dma-write: spe-dma-write.c $(SPECC) $(SPECFLAGS) -o $@ $< libspe2-2.2.80-95/libspe12/tests/dma/spe-dma-write.c0000644000175100017510000000107710600243027021141 0ustar arthurarthur#include "spu_intrinsics.h" typedef union { unsigned long long ull; unsigned int vp[2]; } addr64; int result __attribute__ ((aligned (128))); int main ( int spuid, addr64 argp, addr64 envp) { unsigned long long argAddress = argp.ull; /* Write to specified address */ result = 42; spu_mfcdma32 (&result, argAddress, 4, 0, (((0) << 24) | ((0) << 16) | (0x20))); __builtin_si_wrch((22),__builtin_si_from_uint(1)); spu_mfcstat(0x2); /* Done */ return 0; } libspe2-2.2.80-95/libspe12/tests/dma/ppe-dma-test.c0000644000175100017510000000170110600243027020755 0ustar arthurarthur#include #include #include int main(int argc, char* argv[]) { spe_program_handle_t *binary; speid_t threadnum; int status; static int test_result __attribute__ ((aligned (128))); /* DMA - Write test. */ binary = spe_open_image("spe-dma-write"); if (!binary) exit(2); printf("Test result Addr: %p\n",&test_result); threadnum = spe_create_thread(0, binary, &test_result, NULL, 0, 0); spe_wait(threadnum,&status,0); printf("Thread returned status: %04x\n",status); printf("Test result: %04x\n",test_result); spe_close_image(binary); /* DMA - Read test. */ binary = spe_open_image("spe-dma-read"); if (!binary) exit(2); threadnum = spe_create_thread(0, binary, &test_result, NULL, 0, 0); spe_wait(threadnum,&status,0); printf("Thread returned status: %04x\n",status); printf("Test result: %04x\n",test_result); spe_close_image(binary); return 0; } libspe2-2.2.80-95/libspe12/tests/dma/spe-dma-read.c0000644000175100017510000000112610600243027020715 0ustar arthurarthur#include typedef union { unsigned long long ull; unsigned int vp[2]; } addr64; volatile int result __attribute__ ((aligned (128))); int main (int spuid, addr64 argp, addr64 envp) { unsigned long long argAddress = argp.ull; /* Write to specified address */ result = 23; __builtin_si_wrch((22), __builtin_si_from_uint(1)); spu_mfcdma32((void *) &result, argAddress, 4, 0, (((0) << 24) | ((0) << 16) | (0x40))); spu_mfcstat(0x2); /* Done */ return result; } libspe2-2.2.80-95/libspe12/tests/Makefile0000644000175100017510000000205210600243027017210 0ustar arthurarthur#* #* libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS #* Copyright (C) 2005 IBM Corp. #* #* This library is free software; you can redistribute it and/or modify it #* under the terms of the GNU Lesser General Public License as published by #* the Free Software Foundation; either version 2.1 of the License, #* or (at your option) any later version. #* #* This library is distributed in the hope that it will be useful, but #* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY #* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public #* License for more details. #* #* You should have received a copy of the GNU Lesser General Public License #* along with this library; if not, write to the Free Software Foundation, #* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #* tests: make -C start-stop make -C dma make -C event make -C ft make -C elfspe clean: make -C start-stop clean make -C dma clean make -C event clean make -C ft clean make -C elfspe clean libspe2-2.2.80-95/libspe12/tests/start-stop/0000755000175100017510000000000010707604273017705 5ustar arthurarthurlibspe2-2.2.80-95/libspe12/tests/start-stop/Makefile0000644000175100017510000000246210600243027021335 0ustar arthurarthur#* #* libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS #* Copyright (C) 2005 IBM Corp. #* #* This library is free software; you can redistribute it and/or modify it #* under the terms of the GNU Lesser General Public License as published by #* the Free Software Foundation; either version 2.1 of the License, #* or (at your option) any later version. #* #* This library is distributed in the hope that it will be useful, but #* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY #* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public #* License for more details. #* #* You should have received a copy of the GNU Lesser General Public License #* along with this library; if not, write to the Free Software Foundation, #* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #* CC := gcc SPECC := spu-gcc CTAGS = ctags CFLAGS := -O2 -m32 -Wall -g -I../../../../head-libspe SPECFLAGS := -O2 -Wall LDFLAGS := -m32 LIBS := -L../../../spebase -L../.. -lspe -lspebase -lpthread SPE_OBJS := spe-start-stop OBJS := ppe-start-stop all: $(OBJS) $(SPE_OBJS) clean: rm -f $(OBJS) $(SPE_OBJS) ppe-start-stop: ppe-start-stop.c ../../libspe.a $(CC) -o $@ $< $(CFLAGS) $(LDFLAGS) $(LIBS) spe-start-stop: spe-start-stop.c $(SPECC) $(SPECFLAGS) -o $@ $< libspe2-2.2.80-95/libspe12/tests/start-stop/spe-start-stop.c0000644000175100017510000000171610600243027022747 0ustar arthurarthur/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include int main(void* argp, void* envp) { printf ("SPU: argp=%p , envp=%p\n",argp,envp); return 0; } libspe2-2.2.80-95/libspe12/tests/start-stop/ppe-start-stop.c0000644000175100017510000000322010600243027022734 0ustar arthurarthur/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include int main(int argc, char* argv[]) { spe_program_handle_t *binary; speid_t spe_thread; spe_gid_t spe_group; int max_spe, status; if (argc != 2) { printf("usage: pu spu-executable\n"); exit(1); } binary = spe_open_image(argv[1]); if (!binary) exit(2); spe_group = spe_create_group(SCHED_OTHER, 0, 0); if (!spe_group) { printf("error: create_group.\n"); } max_spe = spe_group_max(spe_group); printf("info: group_max=%i\n", max_spe); spe_thread = spe_create_thread(spe_group, binary, 0x1234, 0xabcd, 0xffff, 0); if (spe_thread) { spe_wait(spe_thread, &status,0); printf("Thread returned status: %04x\n",status); } else perror("Could not create thread"); spe_close_image(binary); return 0; } libspe2-2.2.80-95/libspe12/tests/ft/0000755000175100017510000000000010707604273016176 5ustar arthurarthurlibspe2-2.2.80-95/libspe12/tests/ft/spe-test-ppedma.c0000644000175100017510000000214610600243027021341 0ustar arthurarthur/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include int main(void) { unsigned int data; void *space; space = malloc(64 * 1024); spu_writech(SPU_WrOutIntrMbox, (unsigned long) space); /* wait for signal to finish */ data = spu_readch(SPU_RdInMbox); return 0; } libspe2-2.2.80-95/libspe12/tests/ft/spe-test-start-stop.c0000644000175100017510000000162610600243027022215 0ustar arthurarthur/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include int main(void) { return 0; } libspe2-2.2.80-95/libspe12/tests/ft/spe-test-mboxwait.c0000644000175100017510000000176110600243027021727 0ustar arthurarthur/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include int main(void) { unsigned int data; data = spu_readch(SPU_RdInMbox); spu_writech(SPU_WrOutMbox, data); return 0; } libspe2-2.2.80-95/libspe12/tests/ft/spe-test-block.c0000644000175100017510000000177710600243027021176 0ustar arthurarthur/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include int main(void) { int i,j,a[128]; for(i=0; i< 150000000 ; i++) { for(j=0; j< 128; j++) { a[j] += i; } } return 0; } libspe2-2.2.80-95/libspe12/tests/ft/spe-test-dma-write.c0000644000175100017510000000104710600243027021763 0ustar arthurarthur#include "spu_intrinsics.h" typedef union { unsigned long long ull; unsigned int vp[2]; } addr64; int result __attribute__ ((aligned (128))); int main ( int spuid, addr64 argp, addr64 envp) { unsigned long long argAddress = argp.ull; /* Write to specified address */ result = 42; spu_mfcdma32 (&result, argAddress, 4, 0, (((0) << 24) | ((0) << 16) | (0x20) )); __builtin_si_wrch((22),__builtin_si_from_uint(1)); spu_mfcstat(0x2); /* Done */ return 0; } libspe2-2.2.80-95/libspe12/tests/ft/Makefile0000644000175100017510000000254510600243027017630 0ustar arthurarthur#* #* libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS #* Copyright (C) 2005 IBM Corp. #* #* This library is free software; you can redistribute it and/or modify it #* under the terms of the GNU Lesser General Public License as published by #* the Free Software Foundation; either version 2.1 of the License, #* or (at your option) any later version. #* #* This library is distributed in the hope that it will be useful, but #* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY #* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public #* License for more details. #* #* You should have received a copy of the GNU Lesser General Public License #* along with this library; if not, write to the Free Software Foundation, #* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #* CC := gcc SPECC := spu-gcc CTAGS = ctags CFLAGS := -O2 -m32 -Wall -g -I../../../../head-libspe SPECFLAGS := -O2 -Wall LDFLAGS := -m32 LIBS := -L../../../spebase -L../.. -lspe -lspebase -lpthread SPE_OBJS := spe-test-block spe-test-pause spe-test-start-stop spe-test-mboxwait SPE_OBJS += spe-test-ppedma spe-test-ibox2 spe-test-mbox-block OBJS := ft all: $(OBJS) $(SPE_OBJS) clean: rm -f $(OBJS) $(SPE_OBJS) ft: ft.c $(CC) -o $@ $< $(CFLAGS) $(LDFLAGS) $(LIBS) $(SPE_OBJS): %: %.c $(SPECC) $(SPECFLAGS) -o $@ $< libspe2-2.2.80-95/libspe12/tests/ft/spe-test-mbox-block.c0000644000175100017510000000207410600243027022130 0ustar arthurarthur/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include int main(void) { unsigned int data = 0xaabb; spu_writech(SPU_WrOutIntrMbox, data); si_stop(0x1188); data = 0xccdd; spu_writech(SPU_WrOutIntrMbox, data); si_stop(0x1189); return 0; } libspe2-2.2.80-95/libspe12/tests/ft/spe-test-pause.c0000644000175100017510000000177210600243027021214 0ustar arthurarthur/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include int main(void) { int i,j,a[128]; for(i=0; i< 1500 ; i++) { for(j=0; j< 128; j++) { a[j] += i; } } return 0; } libspe2-2.2.80-95/libspe12/tests/ft/spe-test-event.c0000644000175100017510000000244510600243027021216 0ustar arthurarthur/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include int main(void) { int i,j,a[128]; for(i=0; i< 1500000 ; i++) { for(j=0; j< 128; j++) { a[j] += i; } } si_stop(0x1199); for(i=0; i< 1500000 ; i++) { for(j=0; j< 128; j++) { a[j] += i; } } // spu_writech(mfc_wr_intr_mailbox, 0xaabd); spu_writech(SPU_WrOutIntrMbox, 0xaabd); for(i=0; i< 1500000 ; i++) { for(j=0; j< 128; j++) { a[j] += i; } } si_stop(0x119A); return 0; } libspe2-2.2.80-95/libspe12/tests/ft/spe-test-ibox2.c0000644000175100017510000000256610600243027021124 0ustar arthurarthur/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include void delay(void) { int i,j,a[128]; for(i=0; i< 200000 ; i++) { for(j=0; j< 128; j++) { a[j] += i; } } } int main(void) { unsigned int data; delay(); /* send a first event */ spu_writech(SPU_WrOutIntrMbox, 0xf00); /* wait for app to get it */ data = spu_readch(SPU_RdInMbox); delay(); /* send the second event that used to be broken */ spu_writech(SPU_WrOutIntrMbox, 0xbaa); /* wait for signal to finish */ data = spu_readch(SPU_RdInMbox); return 0; } libspe2-2.2.80-95/libspe12/tests/ft/ft.c0000644000175100017510000006076310600243027016753 0ustar arthurarthur/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include static int basic_test(void) { spe_program_handle_t *binary[16]; speid_t spe_thread[256]; spe_gid_t spe_group; spe_gid_t spe_groups[16]; int result = 0; int i, j, a, max_spe, threads, status, ret; static int test_result __attribute__ ((aligned(128))); /* Basic Test */ printf("\nStep 1: spe_create_group() "); spe_group = spe_create_group(SCHED_OTHER, 0, 0); if (!spe_group) { printf("error: create_group.\n"); result++; } printf("\nStep 1a: spe_destroy_group() "); if (spe_destroy_group(spe_group)) { printf("error: destroy_group.\n"); } if (spe_destroy_group(spe_group)) { printf("Group gone."); } spe_group = spe_create_group(SCHED_OTHER, 0, 0); if (!spe_group) { printf("error: create_group.\n"); result++; } printf(" OK.\n"); printf(" spe_group=%p.\n",spe_group); printf("\nStep 2: spe_group_max() returns:"); max_spe = spe_group_max(spe_group); printf("%i\n", max_spe); printf("\nStep 3: spe_get_threads(spe_gid_t,NULL) returns:"); threads = spe_get_threads(spe_group,NULL); printf("%i ", threads); if(threads) { printf(" ERROR.\n"); result++; } else printf(" OK.\n"); printf("\nStep 4a: spe_open_image(\"spe-test-pause\") "); binary[0] = spe_open_image("spe-test-pause"); if (!binary[0]) { printf(" ERROR.\n"); exit(2); } printf(" OK.\n"); printf("\nStep 4b: spe_open_image(\"spe-test-pause\") (again) "); binary[1] = spe_open_image("spe-test-pause"); if (!binary[1]) { printf(" ERROR.\n"); exit(2); } printf(" OK.\n"); printf("\nStep 5a: spe_create_thread() "); spe_thread[0] = spe_create_thread(spe_group, binary[0], &test_result, NULL, 0xffff, 0); if (!spe_thread[0]) { printf(" ERROR.\n"); exit(2); } else { printf("OK.\n"); printf(" Returned speid=%p\n",spe_thread[0]); } usleep(500000); printf("\nStep 5b: spe_create_thread() (again) "); spe_thread[1] = spe_create_thread(spe_group, binary[1], &test_result, NULL, 0xffff, 0); if (!spe_thread[1]) { printf(" ERROR.\n"); exit(2); } else { printf("OK.\n"); printf(" Returned speid=%p\n",spe_thread[1]); } printf("\nStep 5c: spe_destroy_group() (delayed)"); if (spe_destroy_group(spe_group)) { printf("error: destroy_group.\n"); } printf("\nStep 6: spe_get_threads(spe_gid_t,NULL) returns:"); threads = spe_get_threads(spe_group,NULL); printf("%i ", threads); if (threads != 2) { printf(" ERROR.\n"); result++; } else { speid_t speids[16]; int i; printf(" OK.\n"); threads=spe_get_threads(spe_group,speids); for (i=0 ; i= timeout) { fprintf(stderr, "spe_get_event: probably timed out\n"); return 4; } *data = e.data; if (e.revents != SPE_EVENT_MAILBOX) { fprintf(stderr, "spe_get_event: unexpected event %d\n", e.revents); return 5; } if (e.speid != s) { fprintf(stderr, "spe_get_event: unexpected speid %p\n", e.speid); return 6; } return 0; } static int ppe_ibox_test(void) { spe_program_handle_t *binary; speid_t spe_thread; spe_gid_t spe_group; const uint32_t mbox_magic = 0xDEAD4EAD; uint32_t mbox_data; int status; int ret; static int test_result __attribute__ ((aligned(128))); binary = spe_open_image("spe-test-ppedma"); if (!binary) { perror("spe_open_image"); return 1; } spe_group = spe_create_group(SCHED_OTHER, 0, 0); if (!spe_group) { perror("spe_create_group"); return 2; } spe_thread = spe_create_thread(spe_group, binary, &test_result, NULL, 0xffff, 0); if (!spe_thread) { perror("spe_create_thread"); return 3; } ret = ppe_test_read_ibox(spe_group, spe_thread, &mbox_data); if (ret) return 5; ret = spe_write_in_mbox (spe_thread, mbox_magic); if (ret) { perror("spe_write_in_mbox"); return 6; } ret = spe_wait(spe_thread, &status, 0); if (ret) { perror("spe_wait"); return 7; } return 0; } #if 0 static int ppe_ibox2_test(void) { /* one bug in spufs caused get_event to succeed only once * on the ibox file, so we try it twice here */ spe_program_handle_t *binary; speid_t spe_thread; spe_gid_t spe_group; const uint32_t mbox_magic = 0xDEAD4EAD; uint32_t mbox_data; int status; int ret; static int test_result __attribute__ ((aligned(128))); binary = spe_open_image("spe-test-ibox2"); if (!binary) { perror("spe_open_image"); return 1; } spe_group = spe_create_group(SCHED_OTHER, 0, 0); if (!spe_group) { perror("spe_create_group"); return 2; } spe_thread = spe_create_thread(spe_group, binary, &test_result, NULL, 0xffff, 0); if (!spe_thread) { perror("spe_create_thread"); return 3; } ret = ppe_test_read_ibox(spe_group, spe_thread, &mbox_data); if (ret) return 5; ret = spe_write_in_mbox (spe_thread, mbox_magic); if (ret) { perror("spe_write_in_mbox1"); return 6; } ret = ppe_test_read_ibox(spe_group, spe_thread, &mbox_data); if (ret) return 7; ret = spe_write_in_mbox (spe_thread, mbox_magic); if (ret) { perror("spe_write_in_mbox2"); return 8; } ret = spe_wait(spe_thread, &status, 0); if (ret) { perror("spe_wait"); return 9; } return 0; } #endif static int ppe_dma_test(int (*fn)(speid_t, spe_gid_t, uint32_t, void*)) { spe_program_handle_t *binary; speid_t spe_thread; spe_gid_t spe_group; const uint32_t mbox_magic = 0xDEAD4EAD; uint32_t ls_offs; void *ls_buf; int status; int ret; static int test_result __attribute__ ((aligned(128))); binary = spe_open_image("spe-test-ppedma"); if (!binary) { perror("spe_open_image"); return 1; } spe_group = spe_create_group(SCHED_OTHER, 0, 0); if (!spe_group) { perror("spe_create_group"); return 2; } spe_thread = spe_create_thread(spe_group, binary, &test_result, NULL, 0xffff, 0); if (!spe_thread) { perror("spe_create_thread"); return 3; } ls_buf = spe_get_ls(spe_thread); if (!ls_buf) { perror("spe_get_ls"); return 4; } ret = ppe_test_read_ibox(spe_group, spe_thread, &ls_offs); if (ret) return 5; ls_buf += ls_offs; ret = fn(spe_thread, spe_group, ls_offs, ls_buf); if (ret) return ret; ret = spe_write_in_mbox (spe_thread, mbox_magic); if (ret) { perror("spe_write_in_mbox"); return 9; } ret = spe_wait(spe_thread, &status, 0); if (ret) { perror("spe_wait"); return 10; } return 0; } static int do_ppe_dma_put(speid_t t, spe_gid_t g, uint32_t ls_offs, void *ls_buf) { static const int size = 16 * 1024; static int buf[size / sizeof(int)] __attribute__((aligned(128))); int ret; struct spe_event e = { .gid = g, .events = SPE_EVENT_TAG_GROUP, }; memset(ls_buf, 0, size); memset(buf, 0x5a, size); ret = spe_mfc_put(t, ls_offs, buf, size, 1, 0, 0); if (ret) { perror("do_ppe_dma_put: spe_mfc_put"); return 9; } ret = spe_get_event(&e, 1, 1000); if (!ret) { fprintf(stderr, "do_ppe_dma_put: spe_get_event: timeout\n"); // return 7; } if (memcmp(buf, ls_buf, size) != 0) { fprintf(stderr, "do_ppe_dma_put: miscompare\n"); return 10; } return 0; } static int ppe_dma_put(void) { return ppe_dma_test(do_ppe_dma_put); } static int do_ppe_dma_get(speid_t t, spe_gid_t g, uint32_t ls_offs, void *ls_buf) { static const int size = 16 * 1024; static int buf[size / sizeof(int)] __attribute__((aligned(128))); int ret; struct spe_event e = { .gid = g, .events = SPE_EVENT_TAG_GROUP, }; memset(ls_buf, 0, size); memset(buf, 0x5a, size); ret = spe_mfc_get(t, ls_offs, buf, size, 1, 0, 0); if (ret) { perror("do_ppe_dma_get: spe_mfc_get"); return 9; } ret = spe_get_event(&e, 1, 1000); if (!ret) { fprintf(stderr, "do_ppe_dma_get: spe_get_event: timeout\n"); // return 7; } if (memcmp(buf, ls_buf, size) != 0) { fprintf(stderr, "do_ppe_dma_get: miscompare\n"); return 10; } return 0; } static int ppe_dma_get(void) { return ppe_dma_test(do_ppe_dma_get); } static int do_ppe_dma_mput(speid_t t, spe_gid_t g, uint32_t ls_offs, void *ls_buf) { static const int size = 64 * 1024; static const int fragment = 512; static int buf[size / sizeof(int) * 4] __attribute__((aligned(128))); int ret; struct spe_event e = { .gid = g, .events = SPE_EVENT_TAG_GROUP, }; int i; memset(ls_buf, 0xaa, size); // memset(buf, 0x5a, size); for (i = 0; i < size/(fragment); i++) { ret = spe_mfc_put(t, ls_offs + fragment*i, (void*) buf + fragment *i, fragment, 1, 0, 0); if (ret) { perror("do_ppe_dma_mput: spe_mfc_get"); fprintf(stderr, "count %d\n", i); return 9; } } ret = spe_get_event(&e, 1, 1000); if (!ret) { fprintf(stderr, "do_ppe_dma_mput: spe_get_event: timeout\n"); // return 7; } if (memcmp(buf, ls_buf, size) != 0) { fprintf(stderr, "do_ppe_dma_mput: miscompare\n"); return 10; } return 0; } static int ppe_dma_mput(void) { return ppe_dma_test(do_ppe_dma_mput); } static struct { int (*fn)(void); const char *name; } tests[] = { { basic_test, "basic", }, { ppe_mbox_test, "mbox", }, { ppe_ibox_test, "ibox", }, /* { ppe_ibox2_test, "ibox2", }, */ { ppe_dma_get, "ppeget", }, { ppe_dma_put, "ppeput", }, { ppe_dma_mput, "ppemput", }, }; static const int num_tests = sizeof (tests) / sizeof (tests[0]); int runtest(char *name) { int i, ret; ret = 0; for (i = 0; i < num_tests; i++) { if (strcmp(tests[i].name, name) == 0) { fprintf(stderr, "%02d: %s\n", i, tests[i].name); ret = tests[i].fn(); fprintf(stderr, "%02d: return: %d\n", i, ret); break; } } return ret; } int runalltests(void) { int i, ret; for (i = 0; i < num_tests; i++) { fprintf(stderr, "%02d: %s\n", i, tests[i].name); ret = tests[i].fn(); fprintf(stderr, "%02d: return: %d\n", i, ret); if (ret) break; } return ret; } int main(int argc, char *argv[]) { int i; int ret; ret = 0; if (argc == 1) ret = runalltests(); else for (i = 1; i < argc; i++) { ret = runtest(argv[i]); if (ret) break; } return ret; } libspe2-2.2.80-95/libspe12/ps.c0000644000175100017510000000614010627520105015202 0ustar arthurarthur/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "spe.h" #include "spebase.h" #define __PRINTF(fmt, args...) { fprintf(stderr,fmt , ## args); } #ifdef DEBUG #define DEBUG_PRINTF(fmt, args...) __PRINTF(fmt , ## args) #else #define DEBUG_PRINTF(fmt, args...) #endif void *spe_get_ps_area(speid_t speid, enum ps_area area) { void *base_addr; struct thread_store *spe = speid; if (!srch_thread(speid)){ errno = ESRCH; return NULL; } if (!(spe->flags & SPE_MAP_PS)) { errno = EACCES; return NULL; } if ( area == SPE_MSSYNC_AREA ) { base_addr = _base_spe_ps_area_get(spe->spectx, SPE_MSSYNC_AREA); 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 = _base_spe_ps_area_get(spe->spectx, SPE_MFC_COMMAND_AREA); if (base_addr == NULL) { perror("spe_map_ps_area: internal error. cant map mfc file."); errno = EIO; return NULL; } return base_addr ; } else if ( area == SPE_CONTROL_AREA ) { base_addr = _base_spe_ps_area_get(spe->spectx, SPE_CONTROL_AREA); if (base_addr == NULL) { perror("spe_map_ps_area: internal error. cant map control file."); errno = EIO; return NULL; } return base_addr ; } else if ( area == SPE_SIG_NOTIFY_1_AREA ) { base_addr = _base_spe_ps_area_get(spe->spectx, SPE_SIG_NOTIFY_1_AREA); if (base_addr == NULL) { perror("spe_map_ps_area: internal error. cant map signal1 file."); errno = EIO; return NULL; } return base_addr; } else if ( area == SPE_SIG_NOTIFY_2_AREA ) { base_addr = _base_spe_ps_area_get(spe->spectx, SPE_SIG_NOTIFY_2_AREA); if (base_addr == NULL) { perror("spe_map_ps_area: internal error. cant map signal2 file."); errno = EIO; return NULL; } return base_addr; } perror("spe_map_ps_area: Unsupported call of spe_map_ps_area."); errno = EINVAL; return NULL; } libspe2-2.2.80-95/libspe12/spe.h0000644000175100017510000000715310600243027015355 0ustar arthurarthur/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _spe_h_ #define _spe_h_ /* Definitions */ #define __PRINTF(fmt, args...) { fprintf(stderr,fmt , ## args); } #ifdef DEBUG #define DEBUG_PRINTF(fmt, args...) __PRINTF(fmt , ## args) #else #define DEBUG_PRINTF(fmt, args...) #endif struct thread_store { /* Note: The debugger accesses this data structure, and assumes it starts out with an spe_program_handle_t identifying the SPE executable running within this SPE thread. Everything below is private to libspe. */ spe_program_handle_t handle; pthread_t spe_thread; pthread_cond_t event_deliver; pthread_mutex_t event_lock; int policy, priority, affinity_mask, spe_flags, npc, ret_status,event; spe_gid_t group_id; unsigned long mask; unsigned int flags; unsigned long ev_data; int event_pending; int killed; int stop; int thread_status; /* Below here comes the wrapper code * */ int ev_pipe[2]; spe_context_ptr_t spectx; void *argp; void *envp; void *app_data; }; /*Group members list */ struct grpListElem { struct grpListElem *next; struct thread_store *thread; }; struct group_store { int policy, priority, use_events; struct grpListElem *grp_members; int numListSize; int deleteMe; }; /*Groups List */ struct grpsElem { struct grpsElem *next; struct group_store *group; }; struct group_list { struct grpsElem *list_start; pthread_mutex_t mutex; int numListSize; }; struct spe_ctx { unsigned int npc; unsigned int status; unsigned long reg[128][4]; // size error for LP64 void *ls; }; struct poll_helper { int event; struct thread_store *thread; int type; int retfd; }; /* Low-level SPE execution API. */ extern struct thread_store *srch_thread(struct thread_store *thread); extern struct group_store *srch_group(struct group_store *group); extern int add_group_to_groups(struct group_store *gid); extern int add_thread_to_group(struct group_store *gid, struct thread_store *thread); extern int remove_thread_from_group(struct group_store *gid, struct thread_store *thread); extern void *spe_gid_setup(int policy, int priority, int use_events); extern void *spe_setup (spe_gid_t gid, spe_program_handle_t *handle, void *argp, void *envp, int flags); extern void spe_cleanup (void *spe); 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 register_handler(void * handler, unsigned int callnum ); extern int check_priority(int policy, int priority); extern int remove_group_from_groups(struct group_store *gid); void env_check(void); void * spe_thread (void *ptr); /* * For testing purposes only */ #endif libspe2-2.2.80-95/libspe12/spethreads.c0000644000175100017510000011631410650125273016732 0ustar arthurarthur/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "libspe.h" #include "create.h" #include "spe.h" #include "elf_loader.h" /* * Helpers * * */ static struct group_list grp_list = {NULL,PTHREAD_MUTEX_INITIALIZER,0}; extern int check_env; /* Group defaults * */ int default_priority = 0; int default_policy = SCHED_OTHER; int default_eventmask = 0; //extern void * spe_thread (void *); int add_group_to_groups(struct group_store *gid) { struct grpsElem *listElem; listElem = malloc(sizeof *listElem); if (!listElem) { errno=ENOMEM; return -errno; } pthread_mutex_lock(&grp_list.mutex); listElem->group=gid; listElem->next=grp_list.list_start; grp_list.list_start=listElem; grp_list.numListSize++; pthread_mutex_unlock(&grp_list.mutex); return 0; } int add_thread_to_group(struct group_store *gid, struct thread_store *thread) { struct grpListElem *listElem; listElem = malloc(sizeof *listElem); if (!listElem) { errno=ENOMEM; return -errno; } pthread_mutex_lock(&grp_list.mutex); listElem->thread=thread; listElem->next=gid->grp_members; gid->grp_members=listElem; gid->numListSize++; pthread_mutex_unlock(&grp_list.mutex); return 0; } int remove_group_from_groups(struct group_store *gid) { pthread_mutex_lock(&grp_list.mutex); struct grpsElem *lgp = NULL; for (struct grpsElem *gp=grp_list.list_start ; gp !=NULL; gp=gp->next) { if (gp->group == gid) { if (gp->group->numListSize == 0) { // Delete the group if (lgp == NULL) { grp_list.list_start = gp->next; } else { lgp->next = gp->next; } free(gp); } pthread_mutex_unlock(&grp_list.mutex); return 0; } lgp = gp; } pthread_mutex_unlock(&grp_list.mutex); return 1; } int remove_thread_from_group(struct group_store *gid, struct thread_store *thread) { pthread_mutex_lock(&grp_list.mutex); if (gid->numListSize == 1) { struct grpListElem *p=gid->grp_members; gid->numListSize--; free(p); gid->grp_members = NULL; pthread_mutex_unlock(&grp_list.mutex); if (gid->deleteMe) { remove_group_from_groups(gid); } return 0; } for (struct grpListElem *p=gid->grp_members; p->next!=NULL; p=p->next) { struct grpListElem *np=p->next; if (np->thread==thread) { p->next=np->next; gid->numListSize--; free(np); pthread_mutex_unlock(&grp_list.mutex); return 0; } } pthread_mutex_unlock(&grp_list.mutex); errno = ESRCH; return -ESRCH; } struct thread_store * srch_thread(struct thread_store *thread) { pthread_mutex_lock(&grp_list.mutex); for (struct grpsElem *gp=grp_list.list_start ; gp !=NULL; gp=gp->next) { //printf("1\n"); struct group_store *gid = gp->group; for (struct grpListElem *p=gid->grp_members; p !=NULL; p=p->next) { //printf("2\n"); if (p->thread==thread) { pthread_mutex_unlock(&grp_list.mutex); return p->thread; } } } pthread_mutex_unlock(&grp_list.mutex); errno = ESRCH; return NULL; } struct group_store * srch_group(struct group_store *group) { pthread_mutex_lock(&grp_list.mutex); for (struct grpsElem *gp=grp_list.list_start ; gp !=NULL; gp=gp->next) { if (gp->group == group) { pthread_mutex_unlock(&grp_list.mutex); return gp->group; } } pthread_mutex_unlock(&grp_list.mutex); errno = ESRCH; return NULL; } void * spe_gid_setup(int policy, int priority, int use_events) { struct group_store *group_store; group_store = calloc (1, sizeof *group_store); if (!group_store) { DEBUG_PRINTF ("Could not allocate group store\n"); errno = ENOMEM; return NULL; } group_store->policy = policy; group_store->priority = priority; group_store->use_events = use_events; group_store->grp_members = NULL; group_store->numListSize = 0; group_store->deleteMe = 0; add_group_to_groups(group_store); return group_store; } /** * The spe_create_group function allocates a new SPE thread group. SPE thread groups * define the scheduling policies and priorities for a set of SPE threads. Each SPE * thread belongs to exactly one group. * As an application creates SPE threads, the new threads are added to the designated * SPE group. However the total number of SPE threads in a group cannot exceed the * group maximum, which is dependent upon scheduling policy, priority, and * availability of system resources. The spe_group_max function returns the maximum * allowable number of SPE threads for a group. * All runnable threads in an SPE group may be gang scheduled for execution. * Gang scheduling permits low-latency interaction among SPE threads in shared-memory * parallel applications. * * @param policy Defines the scheduling class for SPE threads in a group. * Accepted values are: * SCHED_RR which indicates real-time round-robin scheduling. * SCHED_FIFO which indicates real-time FIFO scheduling. * SCHED_OTHER which is used for low priority tasks suitable for filling * otherwise idle SPE cycles. * The real-time scheduling policies SCHED_RR and SCHED_FIFO are available * only to processes with super-user privileges. * * @param priority Defines the SPE group's scheduling priority within the policy class. * For the real-time policies SCHED_RR and SCHED_FIFO, priority is a value in the range * of 1 to 99. For interactive scheduling (SCHED_OTHER) the priority is a value in the * range 0 to 99. The priority for an SPE thread group can be modified with * spe_set_priority, or queried with spe_get_priority. * * @param use_events A non-zero value for this parameter allows the application to * receive events for SPE threads in the group. SPE events are conceptually similar * to Linux signals, but differ as follows: SPE events are queued, ensuring that * if multiple events are generated, each is delivered; SPE events are delivered * in the order received; SPE events have associated data, including the type of * event and the SPE thread id. The spe_get_event function can be called to wait * for SPE events. * * @return On success, a positive non-zero identifier for a new SPE group is returned. * On error, zero is returned and errno is set to indicate the error. * Possible errors include: * @retval ENOMEM The SPE group could not be allocated due to lack of system resources. * @retval ENOMEM The total number of SPE groups in the system has reached the system * maximum value. * @retval EINVAL The requested scheduling policy or priority was invalid. * @retval EPERM The process does not have sufficient privileges to create an SPE * group with the requested scheduling policy or priority. * @retval ENOSYS The SPE group could not be allocated due to lack of implementation * support for the specified scheduling priority or policy. * * @sa spe_create_thread(), spe_group_defaults(), spe_group_max(), spe_get_priority(), * spe_set_priority(), spe_get_policy() * */ spe_gid_t spe_create_group (int policy, int priority, int use_events) { struct group_store *group_store; /* Sanity: check for vaild policy/priority combination. */ if (!check_priority(policy, priority)) { errno=EINVAL; return NULL; } DEBUG_PRINTF ("spu_create_group(0x%x, 0x%x, 0x%x)\n", policy, priority, use_events); group_store=spe_gid_setup(policy, priority, use_events); DEBUG_PRINTF("gid is %p\n", group_store); return group_store; } /** * The spe_destroy_group function marks groups to be destroyed, and destroys them * if they do not contain any SPE threads. If a SPE group cannot be destroyed * immediately it will be destroyed after the last SPE thread has ended. * @param spe_gid The identifier of a specific SPE group. * @return 0 on success, -1 on failure. * Possible errors include: * @retval ESRCH The specified SPE group could not be found. * * @sa spe_create_group, spe_get_group */ int spe_destroy_group(spe_gid_t spe_gid) { struct group_store *gid = spe_gid; if ( gid != NULL && !srch_group(gid)) { errno = ESRCH; return -1; } gid->deleteMe=1; remove_group_from_groups(gid); return 0; } /** * The spe_group_max function returns the maximum number of SPE threads that may be * created for an SPE group, as indicated by gid. * The total number of SPE threads in a group cannot exceed the group maximum, * which is dependent upon the group’s scheduling policy, priority, and availability * of system resources. * @param spe_gid This is the identifier of the SPE group. * @return On success, the maximum number of SPE threads allowed for the SPE group * is return. On error, -1 is returned and errno is set appropriately. * Possible errors include: * @retval EPERM The calling process does not have privileges to query the SPE group. * @retval ESRCH The specified SPE group could not be found. * @sa spe_create_group, spe_create_thread */ int spe_group_max (spe_gid_t spe_gid) { char buff[256] = "/sys/devices/system/spu"; DIR *dirp; int ret = -2; struct dirent *dptr; if ( spe_gid != NULL && !srch_group(spe_gid)) { errno = ESRCH; return -1; } DEBUG_PRINTF ("spu_group_max(0x%x)\n", spe_gid); // Count number of SPUs in /sys/devices/system/spu if((dirp=opendir(buff))==NULL) { fprintf(stderr,"Error opening %s ",buff); perror("dirlist"); return MAX_THREADS_PER_GROUP; } while((dptr=readdir(dirp))) { ret++; } closedir(dirp); return ret; } int spe_count_physical_spes(void) { DEBUG_PRINTF ("spe_count_physical_spes()\n"); return _base_spe_cpu_info_get(SPE_COUNT_PHYSICAL_SPES, -1); } /** * spe_create_thread creates a new SPE thread of control that can be executed independently of the calling task. As an application creates SPE threads, the threads are added to the designated SPE group. The total number of SPE threads in a group cannot exceed the group maximum. The spe_group_max function returns the number of SPE threads allowed for the group. * @param gid Identifier of the SPE group that the new thread will belong to. SPE group identifiers are returned by spe_create_group. The new SPE thread inherits scheduling attributes from the designated SPE group. If gid is equal to SPE_DEF_GRP (0), then a new group is created with default scheduling attributes, as set by calling spe_group_defaults. * * @param handle * Indicates the program to be executed on the SPE. This is an opaque pointer to an * SPE ELF image which has already been loaded and mapped into system memory. This * pointer is normally provided as a symbol reference to an SPE ELF executable image * which has been embedded into a PPE ELF object and linked with the calling PPE * program. This pointer can also be established dynamically by loading a shared * library containing an embedded SPE ELF executable, using dlopen(2) and dlsym(2), * or by using the spe_open_image function to load and map a raw SPE ELF executable. * @param argp * An (optional) pointer to application specific data, and is passed as the second * parameter to the SPE program. * @param envp * An (optional) pointer to environment specific data, and is passed as the third * parameter to the SPE program. * @param mask * The processor affinity mask for the new thread. Each bit in the mask enables (1) * or disables (0) thread execution on a cpu. At least one bit in the affinity mask * must be enabled. If equal to -1, the new thread can be scheduled for execution * on any processor. The affinity mask for an SPE thread can be changed by calling * spe_set_affinity, or queried by calling spe_get_affinity. * A bit-wise OR of modifiers that are applied when the new thread is created. The * following values are accepted:\n * 0 No modifiers are applied\n * SPE_CFG_SIGNOTIFY1_OR Configure the Signal Notification 1 Register to be in * 'logical OR' mode instead of the default 'Overwrite' mode.\n * SPE_CFG_SIGNOTIFY2_OR Configure the Signal Notification 1 Register to be in * 'logical OR' mode instead of the default 'Overwrite' mode.\n * SPE_MAP_PS Request permission for memory-mapped access to the SPE thread’s * problem state area(s). Direct access to problem state is a real-time feature, * and may only be available to programs running with privileged authority * (or in Linux, to processes with access to CAP_RAW_IO; see capget(2) for details). * * @param flags SPE_USER_REGS * Specifies that the SPE setup registers r3, r4, and r5 are initialized with the 48 bytes pointed to by argp. * * @return * On success, a positive non-zero identifier of the newly created SPE thread is returned. On error, 0 is returned and errno is set to indicate the error. * Possible errors include: * @retval ENOMEM The SPE thread could not be allocated due to lack of system resources * @retval EINVAL The value passed for mask or flags was invalid. * SPE Thread Management Facilities 5 * @retval EPERM The process does not have permission to add threads to the designated SPE group, or to use the SPU_MAP_PS setting. * @retval ESRCH The SPE group could not be found. * @sa spe_create_group * spe_get_group spe_get_ls * spe_get_ps_area * spe_get_threads * spe_group_defaults * spe_group_max * spe_open_image, spe_close_image */ speid_t spe_create_thread (spe_gid_t gid, spe_program_handle_t *handle, void *argp, void *envp, unsigned long mask, int flags) { struct thread_store *thread_store; int rc; /* Sanity check */ if (!handle || (( flags & SPE_USER_REGS ) && !argp )) { errno=EINVAL; return NULL; } if ( gid != NULL && !srch_group(gid)) { return NULL; } if ( mask == 0 || (mask & ((1<mask = mask; DEBUG_PRINTF ("pthread_create()\n"); rc = pthread_create (&thread_store->spe_thread, NULL, spe_thread, thread_store); if (rc) { perror ("pthread_create"); return NULL; } return thread_store; } static inline int spe_wait_status(unsigned int spe_status_R) { unsigned int rc, term = 0; rc = (spe_status_R & 0xffff0000) >> 16; if (spe_status_R & 0x4) { /* SPE halted. */ term = SIGABRT; } else if (spe_status_R & 0x20) { /* SPE invalid instruction. */ term = SIGILL; } else if (spe_status_R & 0x40) { /* SPE invalid ch. */ term = SIGILL; } else if ((rc < SPE_PROGRAM_NORMAL_END) || (rc > 0x20ff)) { /* Treat these as invalid stop codes. */ term = SIGILL; } else if (spe_status_R & 0x1) { /* Thread killed for undetermined reason. */ term = SIGKILL; } /* Return status that can be evaluated with WIFEXITED(), etc. */ return ((rc & 0xff) << 8) | (term & 0x7f); } /** * spe_wait suspends execution of the current process until the SPE thread specified * by speid has exited. If the SPE thread has already exited by the time of the * call (a so-called “zombie” SPE thread), then the function returns immediately. * Any system resources used by the SPE thread are freed. * @param speid Wait for the SPE thread identified. * @param options This parameter is an logical OR of zero or more of the following * constants:\n * WNOHANG Return immediately if the SPE thread has not exited.\n * WUNTRACED Return if the SPE thread is stopped and its status has not been reported. * @param status If this value is non-NULL, spe_wait stores the SPE thread’s exit c * ode at the address indicated by status. This status can be evaluated with the * following macros. Note: these macros take the status buffer, an int, as a * parameter - not a pointer to the buffer!\n * WIFEXITED(status) Is non-zero if the SPE thread exited normally.\n * WEXITSTATUS(status) Evaluates to the least significant eight bits of the return * code of the SPE thread which terminated, which may have been set as the argument * to a call to exit() or as the argument for a return statement in the main program. * This macro can only be evaluated if WIFEXITED returned non-zero.\n * WIFSIGNALED(status) Returns true if the SPE thread exited because of a signal * which was not caught. * WTERMSIG(status) Returns the number of the signal that caused the SPE thread to * terminate. This macro can only be evaluated if WIFSIGNALED returned non-zero. * WIFSTOPPED(status) Returns true if the SPE thread which caused the return is * currently stopped; this is only possible if the call was done using WUNTRACED. * WSTOPSIG(status) Returns the number of the signal which caused the SPE thread * to stop. This macro can only be evaluated if WIFSTOPPED returned non-zero. * @return On success, 0 is returned. A 0 value is returned if WNOHANG was used and * the SPE thread was available. On failure, -1 is returned and errno is set * appropriately. * Possible errors include: * @retval ESRCH The specified SPE thread could not be found. * @retval EINVAL The options parameter is invalid. * @retval EFAULT status points to an address that was not contained in the calling * process’s address space. * @retval EPERM The calling process does not have permission to wait on the * specified SPE thread. * @retval EAGAIN The wait queue was active at the time spe_wait was called, * prohibiting additional waits, so try again. * * @sa spe_create_thread */ int spe_wait(speid_t speid, int *status, int options) { struct thread_store *thread_store = speid; void *pthread_rc; int rc; if (!srch_thread(speid)) { return -1; } DEBUG_PRINTF("spu_wait(0x%x, 0x%x, 0x%x)\n", speid, *status, options); if (options & WNOHANG) { if (thread_store->thread_status != 99) { *status = 0; return 0; } } if (options & WUNTRACED) { if (thread_store->thread_status == 10 || thread_store->thread_status == 20 ) { *status = 0x4; } } DEBUG_PRINTF("waiting for Thread to end.\n"); rc = pthread_join(thread_store->spe_thread, &pthread_rc); if (rc) { DEBUG_PRINTF(" pthread_join failed, errno=%d\n", errno); return -1; } if (status) { *status = spe_wait_status(thread_store->ret_status); } spe_cleanup(thread_store); DEBUG_PRINTF("Thread ended.\n"); return rc; } /** * The spe_kill can be used to send a control signal to an SPE thread. * @param speid The signal is delivered to the SPE thread identified. * @param sig This indicates the type of control signal to be delivered. * It may be one of the following values:\n * SIGKILL Kill the specified SPE thread.\n * SIGSTOP Stop execution of the specified SPE thread.\n * SIGCONT Resume execution of the specified SPE thread.\n * * @return On success, 0 is returned. On error, -1 is returned and errno is set * appropriately. * Possible errors include: * @retval ENOSYS The spe_kill operation is not supported by the implementation or * environment. * @retval EPERM The calling process does not have permission to perform the kill * action for the receiving SPE thread. * @retval ESRCH The SPE thread does not exist. Note that a existing SPE thread * might be a zombie, an SPE thread which is already committed termination but * yet had spe_wait called for it. * @sa spe_create_thread, spe_wait, kill (2) */ int spe_kill (speid_t speid, int sig) { struct thread_store *thread_store = speid; if (!srch_thread(speid)) { return -1; } if (sig == SIGCONT) { int stopped = 0; pthread_mutex_lock(&thread_store->event_lock); stopped = thread_store->event_pending; if ( thread_store->stop || stopped ) { pthread_cond_signal(&thread_store->event_deliver); } pthread_mutex_unlock(&thread_store->event_lock); return 0; } if (sig == SIGKILL) { int stopped; int ret = 0; pthread_mutex_lock(&thread_store->event_lock); /* Tell the thread that it is to be killed.*/ thread_store->killed = 1; /* See if it is halted and waiting */ stopped = thread_store->event_pending; if (stopped) { pthread_cond_signal(&thread_store->event_deliver); } else { ret = pthread_cancel (thread_store->spe_thread); } pthread_mutex_unlock(&thread_store->event_lock); return ret; } if (sig == SIGSTOP) { /* Tell the thread that it is to stop.*/ thread_store->stop = 1; return 0; } errno = EINVAL; return -1; } int validatefd(struct poll_helper *phelper, int pos, int fd) { int i; for(i=0;igrp_members; DEBUG_PRINTF("spe_get_event():\n"); DEBUG_PRINTF(" using group : %p\n", group); DEBUG_PRINTF(" with members : %i\n", group->numListSize); for ( j=0 ; j < group->numListSize; j++) { struct thread_store *thread = elem->thread; DEBUG_PRINTF(" scan member : %p\n", thread); // Scan for present events in the thread structures of SPEs if (thread->event != 0 && thread->event & pevents[i].events) { int pipeval,ret; DEBUG_PRINTF(" has event ! : 0x%04x\n", thread->event); //Found an event we're looking for. ret_events++; //Fill out return struct. pevents[i].revents = thread->event; pevents[i].speid = thread; pevents[i].data = thread->ev_data; //Empty the pipe ret=read(thread->spectx->base_private->ev_pipe[0], &pipeval, 4); thread->ev_data = 0; thread->event = 0; pthread_mutex_unlock(&grp_list.mutex); return ret_events; } //Decide on what fd's to poll on if (pevents[i].events & (SPE_EVENT_MAILBOX)) { numSPEsToPoll++; } if (pevents[i].events & (SPE_EVENT_TAG_GROUP)) { numSPEsToPoll++; } if (pevents[i].events & (SPE_EVENT_STOP | SPE_EVENT_DMA_ALIGNMENT | SPE_EVENT_SPE_ERROR | SPE_EVENT_SPE_DATA_SEGMENT | SPE_EVENT_SPE_DATA_STORAGE | SPE_EVENT_SPE_TRAPPED | SPE_EVENT_THREAD_EXIT )) { numSPEsToPoll++; } elem=elem->next; } } if(numSPEsToPoll == 0) { pthread_mutex_unlock(&grp_list.mutex); errno=EINVAL; return -1; } if (ret_events > 0) { //printf("P1\n"); //DEBUG_PRINTF(" returning ! : 0xi\n", ret_events); pthread_mutex_unlock(&grp_list.mutex); return ret_events; } DEBUG_PRINTF(" number of fd : %i\n", numSPEsToPoll); SPEfds=malloc (numSPEsToPoll * sizeof(struct pollfd)); phelper=malloc (numSPEsToPoll * sizeof(struct poll_helper)); // Set up all necessary fds to poll on and remeber what they are for. for (i=0 ; i < nevents ; i++) { int j; struct group_store *group = pevents[i].gid; struct grpListElem *elem = group->grp_members; for ( j=0 ; j < group->numListSize; j++) { struct thread_store *thread = elem->thread; if (pevents[i].events & (SPE_EVENT_MAILBOX)) { SPEfds[setupSPEs].fd=_base_spe_open_if_closed(thread->spectx,FD_IBOX, 0); SPEfds[setupSPEs].events=POLLIN; phelper[setupSPEs].event=i; phelper[setupSPEs].thread=thread; phelper[setupSPEs].retfd=-1; phelper[setupSPEs].type=1; //printf("1\n"); setupSPEs++; } if (pevents[i].events & (SPE_EVENT_STOP | SPE_EVENT_DMA_ALIGNMENT | SPE_EVENT_SPE_ERROR | SPE_EVENT_SPE_DATA_SEGMENT | SPE_EVENT_INVALID_DMA_CMD | SPE_EVENT_SPE_DATA_STORAGE | SPE_EVENT_SPE_TRAPPED | SPE_EVENT_THREAD_EXIT )) { SPEfds[setupSPEs].fd=thread->spectx->base_private->ev_pipe[0]; SPEfds[setupSPEs].events=POLLIN; phelper[setupSPEs].event=i; phelper[setupSPEs].thread=thread; phelper[setupSPEs].retfd=-1; phelper[setupSPEs].type=2; //printf("2\n"); setupSPEs++; } if (pevents[i].events & (SPE_EVENT_TAG_GROUP)) { SPEfds[setupSPEs].fd=_base_spe_open_if_closed(thread->spectx,FD_MFC, 0); SPEfds[setupSPEs].events=POLLIN; phelper[setupSPEs].event=i; phelper[setupSPEs].thread=thread; phelper[setupSPEs].retfd=-1; phelper[setupSPEs].type=3; if (SPEfds[setupSPEs].fd == -1) fprintf(stderr, "Warning: spe_get_events: attempting " "to wait for tag group without DMA support\n"); //printf("3\n"); setupSPEs++; } elem=elem->next; } } if (setupSPEs != numSPEsToPoll) { DEBUG_PRINTF("ERROR:Thread number mismatch."); free(SPEfds); free(phelper); pthread_mutex_unlock(&grp_list.mutex); errno = EFAULT; return -1; } pthread_mutex_unlock(&grp_list.mutex); DEBUG_PRINTF("Polling for %i fd events.\n",setupSPEs); pollRet = poll(SPEfds, setupSPEs, timeout); DEBUG_PRINTF("Poll returned %i events.\n",pollRet); ret_events = 0; // Timeout. if (pollRet == 0) { free(SPEfds); free(phelper); return 0; } for (i=0 ; i < setupSPEs ; i++ ) { if (SPEfds[i].revents != 0 && pevents[phelper[i].event].speid == NULL ) { int rc,data; if (validatefd(phelper,i,SPEfds[i].fd)) { switch (phelper[i].type) { case 1: // Read ibox data if present rc = read(SPEfds[i].fd, &data, 4); if (rc == 4) { phelper[i].retfd=SPEfds[i].fd; pevents[phelper[i].event].data = data; pevents[phelper[i].event].speid = phelper[i].thread; pevents[phelper[i].event].revents = SPE_EVENT_MAILBOX; ret_events++; } break; case 2: // Read pipe data if present rc = read(SPEfds[i].fd, &data, 4); //pevents[phelper[i].event].revents = pevents[phelper[i].event].revents | data; phelper[i].retfd=SPEfds[i].fd; pevents[phelper[i].event].revents = data; pevents[phelper[i].event].speid = phelper[i].thread; pevents[phelper[i].event].data = phelper[i].thread->ev_data; phelper[i].thread->ev_data = 0; phelper[i].thread->event = 0; ret_events++; break; case 3: // Read tag group data if present rc = read(SPEfds[i].fd, &data, 4); if (rc == 4) { phelper[i].retfd=SPEfds[i].fd; pevents[phelper[i].event].data = data; pevents[phelper[i].event].speid = phelper[i].thread; pevents[phelper[i].event].revents = SPE_EVENT_TAG_GROUP; ret_events++; } break; } } } } free(SPEfds); free(phelper); //printf("P2\n"); return ret_events; } /** * spe_get_threads returns a list of SPE threads in a group, as indicated by gid, * to the array pointed to by spe_ids. * The storage for the spe_ids array must be allocated and managed by the application. * Further, the spe_ids array must be large enough to accommodate the current number * of SPE threads in the group. The number of SPE threads in a group can be obtained * by setting the spe_ids parameter to NULL. * * @param gid This is the identifier of the SPE group. * @param spe_ids This is a pointer to an array of speid_t values that are filled in * with the ids of the SPE threads in the group specified by gid. * * @return On success, the number of SPE threads in the group is returned. * On failure, -1 is returned and errno is set appropriately. * Possible errors include: * @retval EFAULT The spe_ids array was contained within the calling program’s * address space. * @retval EPERM The current process does not have permission to query SPE threads * for this group. * @retval ESRCH The specified SPE thread group could not be found. * @sa spe_create_group, spe_create_thread */ int spe_get_threads(spe_gid_t gid, speid_t *spe_ids) { struct group_store *group = gid; int i; if ( gid != NULL && !srch_group(gid)) { errno = ESRCH; return -1; } if (!spe_ids) { return group->numListSize; } else { struct grpListElem *elem = group->grp_members; for(i=0; i < group->numListSize ; i++) { spe_ids[i] = elem->thread; elem=elem->next; } } return i; } /** * The scheduling priority for the SPE thread group, as indicated by gid, is * obtained by calling the spe_get_priority. * @param gid The identifier of a specific SPE group. * @return On success, spe_get_priority returns a priority value of 0 to 99. On * failure, spe_get_priority returns -1 and sets errno appropriately. * Possible errors include: * @retval ESRCH The specified SPE thread group could not be found. * @sa spe_create_group */ int spe_get_priority(spe_gid_t gid) { struct group_store *group_store = gid; if ( gid != NULL && !srch_group(gid)) { errno = ESRCH; return -1; } return group_store->priority; } /** * The scheduling priority for the SPE thread group, as indicated by gid is set by * calling the spe_set_priority function. * For the real-time policies SCHED_RR and SCHED_FIFO, priority is a value in the * range of 1 to 99. Only the super-user may modify real-time priorities. * For the interactive policy SCHED_OTHER, priority is a value in the range 0 to 40. * Only the super-user may raise interactive priorities. * * @param gid The identifier of a specific SPE group. * @param priority Specified the SPE thread group’s scheduling priority within the * group’s scheduling policy class. * @return On success, spe_set_priority returns zero. On failure, spe_set_priority * returns -1 and sets errno appropriately. * Possible errors include: * @retval EINVAL The specified priority value is invalid. * @retval EPERM The current process does not have permission to set the specified * SPE thread group priority. * @retval ESRCH The specified SPE thread group could not be found. * @sa spe_create_group */ int spe_set_priority(spe_gid_t gid, int priority) { struct group_store *group_store = gid; /* Sanity: check for vaild policy/priority combination. */ if (!check_priority(group_store->policy, priority)) { errno=EINVAL; return -1; } if ( gid != NULL && !srch_group(gid)) { errno = ESRCH; return -1; } group_store->priority=priority; /*int pthread_setschedparam(pthread_t target_thread, int policy, const struct sched_param *param);*/ return 0; } int check_priority(int policy, int priority) { switch (policy) { case SCHED_RR: if (1 > priority || priority > 99) { return 0; } break; case SCHED_FIFO: if (1 > priority || priority > 99) { return 0; } break; case SCHED_OTHER: if (0 > priority || priority > 40) { return 0; } break; } return 1; } /** * The scheduling policy class for an SPE group is queried by calling the * spe_get_policy function. * * @param gid The identifier of a specific SPE group. * @return On success, spe_get_policy returns a scheduling policy class value * of SCHED_RR, SCHED_FIFO, or SCHED_OTHER. On failure, spe_get_policy returns -1 * and sets errno appropriately. * SPE thread group priority. * @retval ESRCH The specified SPE thread group could not be found. * @sa spe_create_group */ int spe_get_policy(spe_gid_t gid) { struct group_store *group_store = gid; if ( gid != NULL && !srch_group(gid)) { errno = ESRCH; return -1; } return group_store->policy; } /** * The spe_get_group function returns the SPE group identifier for the SPE thread, * as indicated by speid. * @param speid The identifier of a specific SPE thread. * @return The SPE group identifier for an SPE thread, or 0 on failure. * Possible errors include: * @retval ESRCH The specified SPE thread could not be found. * * @sa spe_create_group, spe_get_threads */ spe_gid_t spe_get_group (speid_t speid) { struct thread_store *thread_store = speid; if (!srch_thread(speid)) { return NULL; } return thread_store->group_id; } /** * The spe_set_affinity function sets the processor affinity mask for an SPE thread. * @param speid Identifier of a specific SPE thread. * @param mask The affinity bitmap is represented by the value specified by mask. * The least significant bit corresponds to the first cpu on the system, while the * most significant bit corresponds to the last cpu on the system. A set bit * corresponds to a legally schedulable processor while an unset bit corresponds * to an illegally schedulable processor. In other words, a thread is bound to and * will only run on a cpu whose corresponding bit is set. Usually, all bits in the * mask are set. * @return On success, spe_get_affinity and spe_set_affinity return 0. On failure, * -1 is returned and errno is set appropriately. spe_get_affinity returns the * affinity mask in the memory pointed to by the mask parameter. * Possible errors include: * @retval EFAULT The supplied memory address for mask was invalid. * @retval EINVAL The mask is invalid or cannot be applied. * @retval ENOSYS The affinity setting operation is not supported by the i * mplementation or environment. * @retval ESRCH The specified SPE thread could not be found. * @sa spe_create_thread, sched_setaffinity */ int spe_get_affinity( speid_t speid, unsigned long *mask) { int result = 0; if (!srch_thread(speid)) { return -1; } printf("spe_get_affinity() not implemented in this release.\n"); return result; } /** * The spe_set_affinity function sets the processor affinity mask for an SPE thread. * @param speid Identifier of a specific SPE thread. * @param mask The affinity bitmap is represented by the value specified by mask. * The least significant bit corresponds to the first cpu on the system, while the * most significant bit corresponds to the last cpu on the system. A set bit * corresponds to a legally schedulable processor while an unset bit corresponds * to an illegally schedulable processor. In other words, a thread is bound to and * will only run on a cpu whose corresponding bit is set. Usually, all bits in the * mask are set. * @return On success, spe_get_affinity and spe_set_affinity return 0. On failure, * -1 is returned and errno is set appropriately. spe_get_affinity returns the * affinity mask in the memory pointed to by the mask parameter. * Possible errors include: * @retval EFAULT The supplied memory address for mask was invalid. * @retval EINVAL The mask is invalid or cannot be applied. * @retval ENOSYS The affinity setting operation is not supported by the i * mplementation or environment. * @retval ESRCH The specified SPE thread could not be found. * @sa spe_create_thread, sched_setaffinity */ int spe_set_affinity(speid_t speid, unsigned long mask) { int result = 0; if (!srch_thread(speid)) { return -1; } printf("spe_set_affinity() not implemented in this release.\n"); return result; } /** * spe_group_defaults changes the application defaults for SPE groups. When an * application calls spe_create_thread and designates an SPE group id equal to * SPE_DEF_GRP (0), then a new group is created and the thread is added to the * new group. The group is created with default settings for memory access * privileges and scheduling attributes. By calling spe_group_defaults, the * application can override the settings for these attributes. * The initial attribute values for SPE group 0 are defined as follows: * the policy is set to SCHED_OTHER; the priority is set to 0; and spe_events are * disabled. * * @param policy This defines the scheduling class. Accepted values are:\n * SCHED_RR which indicates real-time round-robin scheduling.\n * SCHED_FIFO which indicates real-time FIFO scheduling.\n * SCHED_OTHER which is used for low priority tasks suitable * for filling otherwise idle SPE cycles.\n * @param priority This defines the default scheduling priority. For the real-time * policies SCHED_RR and SCHED_FIFO, priority is a value in the range of 1 to 99. * For interactive scheduling * (SCHED_OTHER) the priority is a value in the range 0 to 99. * @param spe_events A non-zero value for this parameter registers the application’s * interest iapp_data = data; return 0; } int spe_get_app_data( speid_t speid, void** p_data) { struct thread_store *thread_store = speid; if (!srch_thread(speid)) return -1; *p_data = thread_store->app_data; return 0; } libspe2-2.2.80-95/libspe12/libspe.h0000644000175100017510000002130010627520105016036 0ustar arthurarthur/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _libspe_h_ #define _libspe_h_ #ifdef __cplusplus extern "C" { #endif #include "libspe2.h" typedef void *speid_t; typedef void *spe_gid_t; /* Flags for spe_create_thread */ #define SPE_USER_REGS 0x0002 /* 128b user data for r3-5. */ #define SPE_CFG_SIGNOTIFY1_OR 0x00000010 #define SPE_CFG_SIGNOTIFY2_OR 0x00000020 #define SPE_MAP_PS 0x00000040 #define SPE_DEF_GRP 0x00000000 #define MAX_THREADS_PER_GROUP 16 /* spe user context */ struct spe_ucontext { unsigned int gprs[128][4]; unsigned int fpcr[4]; unsigned int decr; unsigned int decr_status; unsigned int npc; unsigned int tag_mask; unsigned int event_mask; unsigned int srr0; unsigned int _reserved[2]; void * ls; }; /* spe problem state areas */ //enum ps_area { SPE_MSSYNC_AREA, SPE_MFC_COMMAND_AREA, SPE_CONTROL_AREA, SPE_SIG_NOTIFY_1_AREA, SPE_SIG_NOTIFY_2_AREA }; /* SIGSPE maps to SIGURG */ #define SIGSPE SIGURG /* spe_events */ #define SPE_EVENT_MAILBOX 0x0001 /*Interrupting mailbox data */ #define SPE_EVENT_STOP 0x0002 /*SPE 'stop-and-signal data' */ //#define SPE_EVENT_TAG_GROUP 0x0004 /*Tag group complete data */ #define SPE_EVENT_DMA_ALIGNMENT 0x0008 /*A DMA alignment error */ #define SPE_EVENT_SPE_ERROR 0x0010 /*An illegal instruction error*/ #define SPE_EVENT_SPE_DATA_SEGMENT 0x0020 /*A DMA segmentation error */ #define SPE_EVENT_SPE_DATA_STORAGE 0x0040 /*A DMA storage error */ #define SPE_EVENT_SPE_TRAPPED 0x0080 /*SPE 'halt' instruction */ #define SPE_EVENT_THREAD_EXIT 0x0100 /*A thread has exited */ #define SPE_EVENT_ERR 0x0200 /*An error occurred */ #define SPE_EVENT_NVAL 0x0400 /*Invalid request */ #define SPE_EVENT_INVALID_DMA_CMD 0x0800 /*Invalid MFC/DMA command */ struct spe_event { spe_gid_t gid; /* input, SPE group id */ int events; /* input, requested event mask */ int revents; /* output, returned events */ speid_t speid; /* output, returned speid */ unsigned long data; /* output, returned data */ }; /* Signal Targets */ #define SPE_SIG_NOTIFY_REG_1 0x0001 #define SPE_SIG_NOTIFY_REG_2 0x0002 /* APIs for SPE threads. */ extern spe_gid_t spe_create_group (int policy, int priority, int spe_events); extern int spe_group_max (spe_gid_t spe_gid); extern int spe_count_physical_spes(void); extern speid_t spe_create_thread (spe_gid_t gid, spe_program_handle_t *handle, void *argp, void *envp, unsigned long mask, int flags); extern int spe_wait (speid_t speid, int *status, int options); extern int spe_get_event(struct spe_event *pevents, int nevents, int timeout); extern int spe_kill (speid_t speid, int sig); extern int spe_get_priority(spe_gid_t gid); extern int spe_set_priority(spe_gid_t gid, int priority); extern int spe_get_policy(spe_gid_t gid); extern spe_gid_t spe_get_group (speid_t speid); extern void *spe_get_ls(speid_t speid); extern int spe_group_defaults(int policy, int priority, int spe_events); extern int spe_get_threads(spe_gid_t gid, speid_t *spe_ids); extern int spe_destroy_group(spe_gid_t spe_gid); /* Currently without implementation or support */ extern int spe_get_affinity( speid_t speid, unsigned long *mask); extern int spe_set_affinity(speid_t speid, unsigned long mask); extern int spe_get_context(speid_t speid, struct spe_ucontext *uc); extern int spe_set_context(speid_t speid, struct spe_ucontext *uc); /* APIs for loading SPE images */ extern spe_program_handle_t *spe_open_image(const char *filename); extern int spe_close_image(spe_program_handle_t *program_handle); /* =========================================================================== * mfc function wrappers in spe library are defined here. */ /* FUNCTION: spe_write_in_mbox (speid, val) * * Send value to the PPE->SPE mailbox WITHOUT first checking to make sure the * PPE->SPE mailbox queue is NOT FULL. If the queue is full, this would result * in an OVERWRITE of the last mailbox value sent. */ extern int spe_write_in_mbox (speid_t speid ,unsigned int data); /* FUNCTION: spe_stat_in_mbox (speid) * * Returns the status of the PE->SPE mailbox. */ extern int spe_stat_in_mbox (speid_t speid); /* FUNCTION: spe_read_out_mbox (speid) * * Return the contents of the SPE->PPE mailbox without first checking to see * if a new mailbox value is present. This allows for re-read of this * register. */ extern unsigned int spe_read_out_mbox (speid_t speid); /* FUNCTION: spe_stat_out_mbox (speid) * * Returns the status of the SPE->PE mailbox. */ extern int spe_stat_out_mbox (speid_t speid); /* FUNCTION: spe_stat_out_intr_mbox (speid) * * Returns the status of the SPE->PPE interrupting mailbox. */ extern int spe_stat_out_intr_mbox (speid_t speid); /* FUNCTION: spe_write_signal (speid, signal_reg, data) * * Write the data word to the specified SPE signal notification register. */ extern int spe_write_signal (speid_t speid, unsigned int signal_reg, unsigned int data); /* FUNCTION: spe_mfc_put (speid, src, dst, size, tag, tid, rid) * spe_mfc_putf(speid, src, dst, size, tag, tid, rid) * spe_mfc_putb(speid, src, dst, size, tag, tid, rid) * * initiate data transfer from local storage to process memory, * optionally including a fence (putf) or barrier (putb) */ extern int spe_mfc_put (speid_t spe, unsigned src, void *dst, unsigned size, unsigned short tag, unsigned char tid, unsigned char rid); extern int spe_mfc_putf(speid_t spe, unsigned src, void *dst, unsigned size, unsigned short tag, unsigned char tid, unsigned char rid); extern int spe_mfc_putb(speid_t spe, unsigned src, void *dst, unsigned size, unsigned short tag, unsigned char tid, unsigned char rid); /* FUNCTION: spe_mfc_get (speid, dst, src, size, tag, tid, rid) * spe_mfc_getf(speid, dst, src, size, tag, tid, rid) * spe_mfc_getb(speid, dst, src, size, tag, tid, rid) * * initiate data transfer from process memory to local storage * optionally including a fence (getf) or barrier (getb) */ extern int spe_mfc_get (speid_t spe, unsigned dst, void *src, unsigned size, unsigned short tag, unsigned char tid, unsigned char rid); extern int spe_mfc_getf(speid_t spe, unsigned dst, void *src, unsigned size, unsigned short tag, unsigned char tid, unsigned char rid); extern int spe_mfc_getb(speid_t spe, unsigned dst, void *src, unsigned size, unsigned short tag, unsigned char tid, unsigned char rid); /* FUNCTION: spe_mfc_read_tag_status_all(speid, mask); * spe_mfc_read_tag_status_any(speid, mask); * spe_mfc_read_tag_status_immediate(speid, mask); * * read the mfc tag status register. */ extern int spe_mfc_read_tag_status_all(speid_t speid, unsigned int mask); extern int spe_mfc_read_tag_status_any(speid_t speid, unsigned int mask); extern int spe_mfc_read_tag_status_immediate(speid_t speid, unsigned int mask); /* FUNCTION: spe_get_ps_area(speid, ps_area) * * returns a pointer to the problem state area specified by ps_area. */ extern void *spe_get_ps_area (speid_t speid, enum ps_area); /* INOFFICIAL FUNCTION: __spe_get_context_fd(speid) * * returns the file descriptor for the spe context. */ extern int __spe_get_context_fd(speid_t speid); /* FUNCTION: spe_set_app_data(speid, data) * * The spe_set_app_data function associates application specific data with an * SPE thread. Any association with previously associated data is lost on success. * On failure, any previous association is unchanged. */ extern int spe_set_app_data(speid_t speid, void* data); /* FUNCTION: spe_get_app_data(speid, p_data) * * The spe_get_app_data function returns the application specific data associated * with the specified SPE thread as set by spe_set_app_data. If no application * data has been associated with the specified thread, then the memory pointed to * by p_data is set to NULL. */ extern int spe_get_app_data(speid_t speid, void** p_data); #ifdef __cplusplus } #endif #endif libspe2-2.2.80-95/libspe12/Makefile0000644000175100017510000000217210642216516016062 0ustar arthurarthur TOP=.. include $(TOP)/make.defines CFLAGS += -I$(TOP) CFLAGS += -I$(TOP)/spebase CFLAGS += -D_ATFILE_SOURCE LDFLAGS := -m32 LDLIBS := -L$(TOP) -lspe2 -lpthread MAJOR_VERSION := 1 MINOR_VERSION := 2.2 libspe12_A := libspe.a libspe12_SO := libspe.so.${MAJOR_VERSION}.${MINOR_VERSION} libspe12_SONAME := libspe.so.${MAJOR_VERSION} libspe12_OBJS := spe.o spethreads.o dma.o ps.o ../spebase/*.o all: $(libspe12_SO) $(libspe12_A) $(libspe12_A): $(libspe12_OBJS) ar -r $(libspe12_A) $(libspe12_OBJS) $(libspe12_SO): $(libspe12_OBJS) $(CC) $(CFLAGS) -shared -o $@ $^ -lrt -Wl,--soname=${libspe12_SONAME} install: spe.h $(libspe12_SO) $(libspe12_A) $(INSTALL_DIR) $(ROOT)$(libdir) $(INSTALL_DATA) $(libspe12_A) $(ROOT)$(libdir)/$(libspe12_A) $(INSTALL_PROGRAM) $(libspe12_SO) $(ROOT)$(libdir)/$(libspe12_SO) $(INSTALL_LINK) $(libspe12_SO) $(ROOT)$(libdir)/$(libspe12_SONAME) $(INSTALL_LINK) $(libspe12_SONAME) $(ROOT)$(libdir)/libspe.so $(INSTALL_DIR) $(ROOT)$(includedir) $(INSTALL_DATA) libspe.h $(ROOT)$(includedir)/libspe.h clean: rm -f $(libspe12_SO) $(libspe12_OBJS) $(libspe12_A) libspe2-2.2.80-95/libspe12/dma.c0000644000175100017510000001210410650125273015321 0ustar arthurarthur/* libspe - A wrapper library to adapt the JSRE SPE usage model to SPUFS * Copyright (C) 2005 IBM Corp. * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "spe.h" #include "create.h" #define __PRINTF(fmt, args...) { fprintf(stderr,fmt , ## args); } #ifdef DEBUG #define DEBUG_PRINTF(fmt, args...) __PRINTF(fmt , ## args) #else #define DEBUG_PRINTF(fmt, args...) #endif int spe_mfc_put (speid_t spe, unsigned src, void *dst, unsigned size, unsigned short tag, unsigned char tid, unsigned char rid) { struct thread_store *speid = spe; return _base_spe_mfcio_put(speid->spectx, src, dst, size, tag, tid, rid); } int spe_mfc_putf(speid_t spe, unsigned src, void *dst, unsigned size, unsigned short tag, unsigned char tid, unsigned char rid) { struct thread_store *speid = spe; return _base_spe_mfcio_putf(speid->spectx, src, dst, size, tag, tid, rid); } int spe_mfc_putb(speid_t spe, unsigned src, void *dst, unsigned size, unsigned short tag, unsigned char tid, unsigned char rid) { struct thread_store *speid = spe; return _base_spe_mfcio_putb(speid->spectx, src, dst, size, tag, tid, rid); } int spe_mfc_get (speid_t spe, unsigned dst, void *src, unsigned size, unsigned short tag, unsigned char tid, unsigned char rid) { struct thread_store *speid = spe; return _base_spe_mfcio_get(speid->spectx, dst, src, size, tag, tid, rid); } int spe_mfc_getf(speid_t spe, unsigned dst, void *src, unsigned size, unsigned short tag, unsigned char tid, unsigned char rid) { struct thread_store *speid = spe; return _base_spe_mfcio_getf(speid->spectx, dst, src, size, tag, tid, rid); } int spe_mfc_getb(speid_t spe, unsigned dst, void *src, unsigned size, unsigned short tag, unsigned char tid, unsigned char rid) { struct thread_store *speid = spe; return _base_spe_mfcio_getb(speid->spectx, dst, src, size, tag, tid, rid); } /* MFC Read tag status functions * */ static int read_tag_status_noblock(speid_t speid) { struct thread_store *spe = speid; int r_read = 0; unsigned int ret; int mfcfd; mfcfd = _base_spe_open_if_closed(spe->spectx, FD_MFC, 0); r_read = read(mfcfd,&ret,4); if (r_read == 4) { return ret; } return -1; } static int read_tag_status_async(speid_t speid) { struct thread_store *spe = speid; struct pollfd poll_fd; int r_read = 0; unsigned int ret; int mfcfd; mfcfd = _base_spe_open_if_closed(spe->spectx, FD_MFC, 0); poll_fd.fd = mfcfd; poll_fd.events = POLLIN; ret = poll(&poll_fd, 1, -1); if (ret < 0 || !(poll_fd.revents | POLLIN)) return -1; r_read = read(mfcfd,&ret,4); if (r_read == 4) { return ret; } return -1; } int spe_mfc_read_tag_status_all(speid_t speid, unsigned int mask) { int status; if ((status = read_tag_status_noblock(speid)) == -1) return -1; while ((status & mask) != mask) { if ((status = read_tag_status_async(speid)) == -1) return -1; } return status & mask; } int spe_mfc_read_tag_status_any(speid_t speid, unsigned int mask) { int status; if ((status = read_tag_status_noblock(speid)) == -1) return -1; while ((status & mask) == 0) { if ((status = read_tag_status_async(speid)) == -1) return -1; } return status & mask; } int spe_mfc_read_tag_status_immediate(speid_t speid, unsigned int mask) { int status; if ((status = read_tag_status_noblock(speid)) == -1) return -1; return status & mask ; } libspe2-2.2.80-95/libspe12/spe.c0000644000175100017510000004446710600243027015361 0ustar arthurarthur/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "libspe.h" #include "create.h" #include "spe.h" /* * Helpers * * */ int __env_spu_debug_start = 0; int __env_spu_info = 0; int check_env = 1; extern int default_priority; extern int default_policy; extern int default_eventmask; void env_check(void) { if (getenv("SPU_DEBUG_START")) __env_spu_debug_start = strtol ((const char *)getenv("SPU_DEBUG_START"),(char **)NULL, 0); if (getenv("SPU_INFO")) __env_spu_info = strtol ((const char *)getenv("SPU_INFO"),(char **)NULL, 0); check_env = 0; } /** * Low-level API * */ void * spe_setup (spe_gid_t gid, spe_program_handle_t *handle, void *argp, void *envp, int flags) { struct thread_store *thread_store; int rc, sigfd; if(!gid) { gid=spe_gid_setup(default_policy,default_priority,default_eventmask); } else { struct group_store *grp = gid; if (grp->numListSize == MAX_THREADS_PER_GROUP) { DEBUG_PRINTF ("Thread group has reached maximum number of members.\n"); errno = ENOMEM; return NULL; } } /*Allocate thread structure */ thread_store = calloc (1, sizeof *thread_store); if (!thread_store) { DEBUG_PRINTF ("Could not allocate thread store\n"); errno = ENOMEM; return NULL; } flags = SPE_EVENTS_ENABLE | flags; thread_store->group_id = gid; thread_store->flags = flags; DEBUG_PRINTF ("thread_store->flags %08x\n", thread_store->flags); thread_store->argp = argp; thread_store->envp = envp; thread_store->spectx = _base_spe_context_create(flags,NULL,NULL); if (!thread_store->spectx) { DEBUG_PRINTF ("Could not create SPE\n"); return NULL; } rc = _base_spe_program_load(thread_store->spectx, handle); if (rc) { DEBUG_PRINTF ("Could not load SPE\n"); return NULL; } rc = pipe(thread_store->spectx->base_private->ev_pipe); if (rc) thread_store->spectx->base_private->ev_pipe[0] = thread_store->spectx->base_private->ev_pipe[1] = -1; rc = add_thread_to_group(gid, thread_store); /* Register SPE image start address as "object-id" for oprofile. */ //sprintf (signame, "%s/object-id", pathname); sigfd = openat (__base_spe_spe_dir_get(thread_store->spectx),"object-id", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); if (sigfd >= 0) { char buf[100]; sprintf (buf, "%p", handle->elf_image); write (sigfd, buf, strlen (buf) + 1); close (sigfd); } thread_store->stop = 0; return thread_store; } void spe_cleanup (void *ptr) { struct thread_store *thread_store = ptr; _base_spe_context_destroy(thread_store->spectx); remove_thread_from_group(thread_store->group_id, thread_store); free (thread_store); } int do_spe_run (void *ptr) { struct thread_store *thread_store = ptr; unsigned int npc = SPE_DEFAULT_ENTRY; spe_stop_info_t stop_info; int ret; DEBUG_PRINTF ("do_spe_run\n"); thread_store->thread_status = 1; /* Note: in order to be able to kill a running SPE thread the * spe thread must be cancelable. */ pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL); do { thread_store->thread_status = 2; DEBUG_PRINTF ("calling _base_spe_context_run\n"); ret = _base_spe_context_run(thread_store->spectx, &npc,0, thread_store->argp, thread_store->envp, &stop_info); DEBUG_PRINTF ("_base_spe_context_run() result: npc=0x%08x ret=%08x\n", npc, ret); thread_store->thread_status = 10; //SPE _not_ running. /* If a signal was sent to STOP execution we will pause and wait * for a continue signal before going on. */ if ( thread_store->stop ) { pthread_mutex_lock(&thread_store->event_lock); pthread_cond_init(&thread_store->event_deliver, NULL); thread_store->thread_status = 20; //SPE _pausing_. /* Now wait for the continue signal */ pthread_cond_wait(&thread_store->event_deliver, &thread_store->event_lock); pthread_mutex_unlock(&thread_store->event_lock); thread_store->stop = 0; thread_store->thread_status = 10; //SPE _not_ running. } if (ret < 0) { pthread_mutex_lock(&thread_store->event_lock); pthread_cond_init(&thread_store->event_deliver, NULL); switch(errno){ case EIO: DEBUG_PRINTF ("received EIO. stop_info.result.spe_runtime_exception %d \n", stop_info.result.spe_runtime_exception ); thread_store->event = stop_info.result.spe_runtime_exception; DEBUG_PRINTF ("thread_store->event %X\n", &thread_store->event); thread_store->ev_data = stop_info.result.spe_runtime_exception; write(thread_store->spectx->base_private->ev_pipe[1], &thread_store->event, 4); break; case EFAULT: DEBUG_PRINTF ("received EFAULT. stop_info.result.spe_runtime_exception %d \n", stop_info.result.spe_runtime_exception ); switch(stop_info.result.spe_runtime_exception){ case 4: thread_store->event = SPE_EVENT_SPE_TRAPPED; break; case 32: thread_store->event = SPE_EVENT_SPE_ERROR; break; default: thread_store->event = stop_info.result.spe_runtime_exception; } DEBUG_PRINTF ("thread_store->event %X\n", &thread_store->event); thread_store->ev_data = stop_info.result.spe_runtime_exception; write(thread_store->spectx->base_private->ev_pipe[1], &thread_store->event, 4); break; default: DEBUG_PRINTF ("received %d.\n", errno); } pthread_mutex_unlock(&thread_store->event_lock); thread_store->stop = 1; thread_store->thread_status = 99; return stop_info.spu_status; }// else if (ret > 0) { if (ret > 0) { pthread_mutex_lock(&thread_store->event_lock); pthread_cond_init(&thread_store->event_deliver, NULL); if (((struct group_store*)thread_store->group_id)->use_events) { int callnum = ret; // // Event - driven 21xx hanlers // thread_store->event = SPE_EVENT_STOP; thread_store->ev_data = callnum; // //Todo Error handling // write(thread_store->spectx->base_private->ev_pipe[1], &thread_store->event, 4); //Show that we're waiting thread_store->event_pending = 1; // Wait for a signal. pthread_cond_wait(&thread_store->event_deliver, &thread_store->event_lock); thread_store->event_pending = 0; pthread_mutex_unlock(&thread_store->event_lock); } else { pthread_mutex_unlock(&thread_store->event_lock); DEBUG_PRINTF ("SPE user events not enabled.\n"); thread_store->thread_status = 99; return -ENOSYS; } } } while (ret != 0 && !thread_store->killed ); DEBUG_PRINTF ("SPE thread result: %08x:%04x\n", npc, ret); /* Save status & npc */ thread_store->npc = npc; thread_store->ret_status = stop_info.spu_status; // //Event code // if (((struct group_store*)thread_store->group_id)->use_events) { thread_store->event = SPE_EVENT_THREAD_EXIT; thread_store->ev_data = stop_info.stop_reason; // //Todo Error handling // write(thread_store->spectx->base_private->ev_pipe[1], &thread_store->event, 4); } thread_store->thread_status = 99; return stop_info.spu_status; } struct image_handle { spe_program_handle_t speh; unsigned int map_size; }; /** * spe_open_image 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. * * @param filename Specifies the filename of an SPE ELF executable to be loaded * and mapped into system memory. * * @return 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 errors include: * @retval EACCES The calling process does not have permission to access the * specified file. * @retval 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. * @sa spe_create_thread */ spe_program_handle_t *spe_open_image(const char *filename) { return _base_spe_image_open(filename); } /** * spe_close_image unmaps an SPE ELF object that was previously mapped using * spe_open_image. * @param handle handle to open file * * @return On success, spe_close_image returns 0. On failure, -1 is returned and errno is * set appropriately. * @retval EINVAL From spe_close_image, this indicates that the file, specified by * filename, was not previously mapped by a call to spe_open_image. */ int spe_close_image(spe_program_handle_t *handle) { return _base_spe_image_close(handle); } void register_handler(void * handler, unsigned int callnum ) { _base_spe_callback_handler_register(handler, callnum, SPE_CALLBACK_NEW); } /** * Library API * */ void * spe_thread (void *ptr) { /* If the SPU_INFO (or SPU_DEBUG_START) environment variable is set, output a message to stderr telling the user how to attach a debugger to the new SPE thread. */ if (__env_spu_debug_start || __env_spu_info) { int tid = syscall (__NR_gettid); fprintf (stderr, "Starting SPE thread %p, to attach debugger use: spu-gdb -p %d\n", ptr, tid); /* In the case of SPU_DEBUG_START, actually wait until the user *has* attached a debugger to this thread. This is done here by doing an sigwait on the empty set, which will return with EINTR after the debugger has attached. */ if (__env_spu_debug_start) { sigset_t set; sigemptyset (&set); /* Use syscall to avoid glibc looping on EINTR. */ syscall (__NR_rt_sigtimedwait, &set, (void *) 0, (void *) 0, _NSIG / 8); } } return (void *) (unsigned long) do_spe_run (ptr); } /** * The spe_get_ls function returns the address of the local storage * for the SPE thread indicated by speid. * * @param speid The identifier of a specific SPE thread. * @return On success, a non-NULL pointer is returned. On failure, NULL is returned * and errno is set appropriately. Possible errors include: * @retval ENOSYS Access to the local store of an SPE thread is not supported by * the operating system. * @retval ESRCH The specified SPE thread could not be found. * @sa spe_create_group, spe_get_ps_area */ void *spe_get_ls (speid_t speid) { struct thread_store *thread_store = speid; if (!srch_thread(speid)) return NULL; return _base_spe_ls_area_get(thread_store->spectx); } /** * The spe_get_context call returns the SPE user context for an SPE thread. * @param speid Specifies the SPE thread * @param uc Points to the SPE user context structure. * * @return On failure, -1 is returned and errno is set appropriately. * * @sa spe_kill, spe_create_thread, spe_wait, getcontext, setcontect */ int spe_get_context(speid_t speid, struct spe_ucontext *uc) { printf("spe_get_context: not implemented in this release.\n"); errno=ENOSYS; return -1; } /** * The spe_set_context call sets the SPE user context for an SPE thread. * @param speid Specifies the SPE thread * @param uc Points to the SPE user context structure. * * @return On failure, -1 is returned and errno is set appropriately. * * @sa spe_kill, spe_create_thread, spe_wait, getcontext, setcontect */ int spe_set_context(speid_t speid, struct spe_ucontext *uc) { printf("spe_set_context: not implemented in this release.\n"); errno=ENOSYS; return -1; } int __spe_get_context_fd(speid_t speid) { struct thread_store *thread_store = speid; if (!srch_thread(speid)) return -1; return __base_spe_spe_dir_get(thread_store->spectx); } /* * mfc.h direct call-ins * * */ /** * The spe_write_in_mbox function places the 32-bit message specified by data into * the SPU inbound mailbox for the SPE thread specified by the speid parameter. * If the mailbox is full, then spe_write_in_mbox can overwrite the last entry in * the mailbox. The spe_stat_in_mbox function can be called to ensure that space is * available prior to writing to the inbound mailbox. * * @param speid Specifies the SPE thread whose outbound mailbox is to be read. * @param data The 32-bit message to be written into the SPE’s inbound mailbox. * @return On success, spe_write_in_mbox returns 0. On failure, -1 is returned. * @sa spe_read_out_mbox, spe_stat_in_mbox. Spe_stat_out_mbox, * spe_stat_out_intr_mbox, write (2) */ int spe_write_in_mbox (speid_t speid ,unsigned int data) { struct thread_store *thread_store = speid; int rc; if (!srch_thread(speid)) return -1; if (thread_store->thread_status == 99) return -1; rc = _base_spe_in_mbox_write(thread_store->spectx, &data, 1, SPE_MBOX_ALL_BLOCKING); if (rc == 1) rc = 0; return rc; } /** * The spe_stat_in_mbox 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. * * @param speid Specifies the SPE thread whose mailbox status is to be read. * @return On success, returns the current status of the mailbox, respectively. * On failure, -1 is returned. * @sa spe_read_out_mbox, spe_write_in_mbox, read (2) */ int spe_stat_in_mbox (speid_t speid) { struct thread_store *thread_store = speid; if (!srch_thread(speid)) return -1; return _base_spe_in_mbox_status(thread_store->spectx); } /** * The spe_read_out_mbox function returns the contents of the SPU outbound mailbox * for the SPE thread specified by the speid parameter. This read is non-blocking * and returns -1 if no mailbox data is available. * The spe_stat_out_mbox function can be called to ensure that data is available * prior to reading the outbound mailbox. * @param speid Specifies the SPE thread whose outbound mailbox is to be read. * @return On success, spe_read_out_mbox returns the next 32-bit mailbox message. * On failure, -1 is returned. * @sa spe_stat_in_mbox, spe_stat_out_mbox, spe_stat_out_intr_mbox, * spe_write_in_mbox, read (2) */ unsigned int spe_read_out_mbox (speid_t speid) { struct thread_store *thread_store = speid; int rc; unsigned int ret; if (!srch_thread(speid)) return -1; rc = _base_spe_out_mbox_read(thread_store->spectx, &ret, 1); if (rc != 1) ret = -1; return ret; } /** * The spe_stat_out_mbox 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. * * @param speid Specifies the SPE thread whose mailbox status is to be read. * @return On success, returns the current status of the mailbox, respectively. * On failure, -1 is returned. * @sa spe_read_out_mbox, spe_write_in_mbox, read (2) */ int spe_stat_out_mbox (speid_t speid) { struct thread_store *thread_store = speid; if (!srch_thread(speid)) return -1; return _base_spe_out_mbox_status(thread_store->spectx); } /** * The spe_stat_out_intr_mbox 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. * * @param speid Specifies the SPE thread whose mailbox status is to be read. * @return On success, returns the current status of the mailbox, respectively. * On failure, -1 is returned. * @sa spe_read_out_mbox, spe_write_in_mbox, read (2) */ int spe_stat_out_intr_mbox (speid_t speid) { struct thread_store *thread_store = speid; if (!srch_thread(speid)) return -1; return _base_spe_out_intr_mbox_status(thread_store->spectx); } /** * The spe_write_signal function writes data to the signal notification register * specified by signal_reg for the SPE thread specified by the speid parameter. * * @param speid Specifies the SPE thread whose signal register is to be written to. * @param signal_reg Specified the signal notification register to be written. * Valid signal notification registers are:\n * SPE_SIG_NOTIFY_REG_1 SPE signal notification register 1\n * SPE_SIG_NOTIFY_REG_2 SPE signal notification register 2\n * @param data The 32-bit data to be written to the specified signal notification * register. * @return On success, spe_write_signal returns 0. On failure, -1 is returned. * @sa spe_get_ps_area, spe_write_in_mbox */ int spe_write_signal (speid_t speid, unsigned int signal_reg, unsigned int data) { struct thread_store *thread_store = speid; if (!srch_thread(speid)) return -1; if (thread_store->thread_status == 99) return -1; return _base_spe_signal_write(thread_store->spectx, signal_reg, data); } /* * */