summaryrefslogtreecommitdiff
path: root/gcell/lib/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'gcell/lib/runtime')
-rw-r--r--gcell/lib/runtime/.gitignore8
-rw-r--r--gcell/lib/runtime/Makefile.am66
-rw-r--r--gcell/lib/runtime/gc_aligned_alloc.cc55
-rw-r--r--gcell/lib/runtime/gc_client_thread_info.h81
-rw-r--r--gcell/lib/runtime/gc_jd_queue.c78
-rw-r--r--gcell/lib/runtime/gc_jd_stack.c168
-rw-r--r--gcell/lib/runtime/gc_job_manager.cc186
-rw-r--r--gcell/lib/runtime/gc_job_manager_impl.cc1404
-rw-r--r--gcell/lib/runtime/gc_job_manager_impl.h274
-rw-r--r--gcell/lib/runtime/gc_proc_def_utils.cc123
-rw-r--r--gcell/lib/runtime/gc_proc_def_utils.h42
-rwxr-xr-xgcell/lib/runtime/gcell-embedspu-libtool40
-rw-r--r--gcell/lib/runtime/qa_gcell_runtime.cc43
-rw-r--r--gcell/lib/runtime/qa_gcell_runtime.h35
-rw-r--r--gcell/lib/runtime/qa_jd_queue.cc78
-rw-r--r--gcell/lib/runtime/qa_jd_queue.h42
-rw-r--r--gcell/lib/runtime/qa_jd_stack.cc67
-rw-r--r--gcell/lib/runtime/qa_jd_stack.h42
-rw-r--r--gcell/lib/runtime/qa_job_manager.cc790
-rw-r--r--gcell/lib/runtime/qa_job_manager.h89
-rw-r--r--gcell/lib/runtime/spu/.gitignore10
-rw-r--r--gcell/lib/runtime/spu/gc_delay.c58
-rw-r--r--gcell/lib/runtime/spu/gc_logging.c77
-rw-r--r--gcell/lib/runtime/spu/gc_main.c731
-rw-r--r--gcell/lib/runtime/spu/gc_random.c44
-rw-r--r--gcell/lib/runtime/spu/gc_spu_config.h39
-rw-r--r--gcell/lib/runtime/spu/gc_spu_jd_queue.c123
-rw-r--r--gcell/lib/runtime/spu/gcell_runtime_qa.c105
-rw-r--r--gcell/lib/runtime/spu/spu_buffers.c35
-rw-r--r--gcell/lib/runtime/spu/spu_buffers.h32
30 files changed, 0 insertions, 4965 deletions
diff --git a/gcell/lib/runtime/.gitignore b/gcell/lib/runtime/.gitignore
deleted file mode 100644
index a02b6ff73..000000000
--- a/gcell/lib/runtime/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-/Makefile
-/Makefile.in
-/.la
-/.lo
-/.deps
-/.libs
-/*.la
-/*.lo
diff --git a/gcell/lib/runtime/Makefile.am b/gcell/lib/runtime/Makefile.am
deleted file mode 100644
index 3ce637636..000000000
--- a/gcell/lib/runtime/Makefile.am
+++ /dev/null
@@ -1,66 +0,0 @@
-#
-# Copyright 2007,2008,2010 Free Software Foundation, Inc.
-#
-# This file is part of GNU Radio
-#
-# GNU Radio is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-#
-# GNU Radio 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 General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-
-include $(top_srcdir)/Makefile.common
-
-IBM_PPU_SYNC_INCLUDES = -I$(top_srcdir)/gcell/ibm/sync/ppu_source
-
-
-AM_CPPFLAGS = $(DEFINES) $(GCELL_INCLUDES) $(IBM_PPU_SYNC_INCLUDES) \
- $(BOOST_CPPFLAGS) $(CPPUNIT_INCLUDES) $(WITH_INCLUDES)
-
-
-dist_bin_SCRIPTS = gcell-embedspu-libtool
-
-noinst_LTLIBRARIES = libruntime.la libruntime-qa.la
-
-libruntime_la_SOURCES = \
- gc_aligned_alloc.cc \
- gc_job_manager.cc \
- gc_job_manager_impl.cc \
- gc_jd_queue.c \
- gc_jd_stack.c \
- gc_proc_def_utils.cc
-
-libruntime_qa_la_SOURCES = \
- qa_gcell_runtime.cc \
- qa_jd_queue.cc \
- qa_jd_stack.cc \
- qa_job_manager.cc
-
-
-noinst_HEADERS = \
- gc_client_thread_info.h \
- gc_job_manager_impl.h \
- gc_proc_def_utils.h \
- qa_jd_queue.h \
- qa_jd_stack.h \
- qa_job_manager.h \
- qa_gcell_runtime.h
-
-# generate a libtool.lo that contains an embeded SPU executable
-gcell_runtime_qa.lo: ../spu/gcell_runtime_qa
- $(GCELL_EMBEDSPU_LIBTOOL) $< $@
-
-libruntime_qa_la_LIBADD = \
- gcell_runtime_qa.lo \
- libruntime.la
-
-CLEANFILES = gcell_runtime_qa.lo
diff --git a/gcell/lib/runtime/gc_aligned_alloc.cc b/gcell/lib/runtime/gc_aligned_alloc.cc
deleted file mode 100644
index 905154e3d..000000000
--- a/gcell/lib/runtime/gc_aligned_alloc.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2008 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <gcell/gc_aligned_alloc.h>
-#include <stdlib.h>
-#include <stdexcept>
-#include <string.h>
-
-// custom deleter of anything that can be freed with "free"
-class free_deleter {
-public:
- void operator()(void *p) {
- free(p);
- }
-};
-
-void *
-gc_aligned_alloc(size_t size, size_t alignment)
-{
- void *p = 0;
- if (posix_memalign(&p, alignment, size) != 0){
- perror("posix_memalign");
- throw std::runtime_error("memory");
- }
- memset(p, 0, size); // zero the memory
- return p;
-}
-
-boost::shared_ptr<void>
-gc_aligned_alloc_sptr(size_t size, size_t alignment)
-{
- return boost::shared_ptr<void>(gc_aligned_alloc(size, alignment),
- free_deleter());
-}
diff --git a/gcell/lib/runtime/gc_client_thread_info.h b/gcell/lib/runtime/gc_client_thread_info.h
deleted file mode 100644
index e49c07097..000000000
--- a/gcell/lib/runtime/gc_client_thread_info.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007,2010 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef INCLUDED_GC_CLIENT_THREAD_INFO_H
-#define INCLUDED_GC_CLIENT_THREAD_INFO_H
-
-#include <boost/thread.hpp>
-#include <boost/utility.hpp>
-
-enum gc_ct_state {
- CT_NOT_WAITING,
- CT_WAIT_ALL,
- CT_WAIT_ANY,
-};
-
-/*
- * \brief per client-thread data used by gc_job_manager
- *
- * "Client threads" are any threads that invoke methods on
- * gc_job_manager. We use pthread_set_specific to store a pointer to
- * one of these for each thread that comes our way.
- */
-class gc_client_thread_info : boost::noncopyable {
-public:
- gc_client_thread_info() :
- d_free(1), d_cond(), d_state(CT_NOT_WAITING),
- d_jobs_done(0), d_njobs_waiting_for(0),
- d_jobs_waiting_for(0){ }
-
- ~gc_client_thread_info() {
- d_free = 1;
- d_state = CT_NOT_WAITING;
- d_jobs_done = 0;
- d_njobs_waiting_for = 0;
- d_jobs_waiting_for = 0;
- }
-
- //! is this cti free? (1->free, 0->in use)
- uint32_t d_free;
-
- //! which client info are we?
- uint16_t d_client_id;
-
- //! hold this mutex to manipulate anything below here
- boost::mutex d_mutex;
-
- //! signaled by event handler to wake client thread up
- boost::condition_variable d_cond;
-
- //! Is this client waiting?
- gc_ct_state d_state;
-
- //! Jobs that have finished and not yet been waited for (bitvector)
- unsigned long *d_jobs_done;
-
- //! # of jobs we're waiting for
- unsigned int d_njobs_waiting_for;
-
- //! Jobs that client thread is waiting for
- gc_job_desc **d_jobs_waiting_for;
-
-};
-
-#endif /* INCLUDED_GC_CLIENT_THREAD_INFO_H */
diff --git a/gcell/lib/runtime/gc_jd_queue.c b/gcell/lib/runtime/gc_jd_queue.c
deleted file mode 100644
index aeabd305a..000000000
--- a/gcell/lib/runtime/gc_jd_queue.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/* -*- c -*- */
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <gcell/gc_jd_queue.h>
-#include <gcell/memory_barrier.h>
-#include <mutex_init.h>
-#include <mutex_lock.h>
-#include <mutex_unlock.h>
-
-void
-gc_jd_queue_init(gc_jd_queue_t *q)
-{
- _mutex_init(ptr_to_ea(&q->mutex));
- q->head = 0;
- q->tail = 0;
- smp_wmb();
-}
-
-void
-gc_jd_queue_enqueue(gc_jd_queue_t *q, gc_job_desc_t *item)
-{
- item->sys.next = 0;
- _mutex_lock(ptr_to_ea(&q->mutex));
- smp_rmb(); // import barrier
-
- if (q->tail == 0){ // currently empty
- q->tail = q->head = jdp_to_ea(item);
- }
- else { // not empty, append
- ea_to_jdp(q->tail)->sys.next = jdp_to_ea(item);
- q->tail = jdp_to_ea(item);
- }
-
- smp_wmb(); // orders stores above before clearing of mutex
- _mutex_unlock(ptr_to_ea(&q->mutex));
-}
-
-gc_job_desc_t *
-gc_jd_queue_dequeue(gc_jd_queue_t *q)
-{
- _mutex_lock(ptr_to_ea(&q->mutex));
- smp_rmb(); // import barrier
-
- gc_eaddr_t item_ea = q->head;
- if (item_ea == 0){ // empty
- _mutex_unlock(ptr_to_ea(&q->mutex));
- return 0;
- }
-
- q->head = ea_to_jdp(item_ea)->sys.next;
- if (q->head == 0) // now emtpy
- q->tail = 0;
-
- gc_job_desc_t *item = ea_to_jdp(item_ea);
- item->sys.next = 0;
-
- smp_wmb(); // orders stores above before clearing of mutex
- _mutex_unlock(ptr_to_ea(&q->mutex));
- return item;
-}
diff --git a/gcell/lib/runtime/gc_jd_stack.c b/gcell/lib/runtime/gc_jd_stack.c
deleted file mode 100644
index 4d865acf0..000000000
--- a/gcell/lib/runtime/gc_jd_stack.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/* -*- c -*- */
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <gcell/gc_jd_stack.h>
-#include <gcell/memory_barrier.h>
-
-/*
- * begin extract from ppu_intrinics.h
- * FIXME handle this a different way
- */
-
-#if !defined(__PPU__) && !defined(__ppc__) && !defined(__ppc64__)
- && !defined(__GNUC__)
- #error ppu_intrinsics.h included on wrong platform/compiler
-#endif
-
-#define __lwarx(base) __extension__ \
- ({unsigned int result; \
- typedef struct {char a[4];} wordsize; \
- wordsize *ptrp = (wordsize*)(base); \
- __asm__ volatile ("lwarx %0,%y1" \
- : "=r" (result) \
- : "Z" (*ptrp)); \
- result; })
-
-#ifdef __powerpc64__
-#define __ldarx(base) __extension__ \
- ({unsigned long long result; \
- typedef struct {char a[8];} doublewordsize; \
- doublewordsize *ptrp = (doublewordsize*)(base); \
- __asm__ volatile ("ldarx %0,%y1" \
- : "=r" (result) \
- : "Z" (*ptrp)); \
- result; })
-#endif /* __powerpc64__ */
-
-#define __stwcx(base, value) __extension__ \
- ({unsigned int result; \
- typedef struct {char a[4];} wordsize; \
- wordsize *ptrp = (wordsize*)(base); \
- __asm__ volatile ("stwcx. %2,%y1\n" \
- "\tmfocrf %0,0x80" \
- : "=r" (result), \
- "=Z" (*ptrp) \
- : "r" (value)); \
- ((result & 0x20000000) >> 29); })
-
-
-#ifdef __powerpc64__
-#define __stdcx(base, value) __extension__ \
- ({unsigned long long result; \
- typedef struct {char a[8];} doublewordsize; \
- doublewordsize *ptrp = (doublewordsize*)(base); \
- __asm__ volatile ("stdcx. %2,%y1\n" \
- "\tmfocrf %0,0x80" \
- : "=r" (result), \
- "=Z" (*ptrp) \
- : "r" (value)); \
- ((result & 0x20000000) >> 29); })
-#endif /* __powerpc64__ */
-
-
-/*
- * --- end extract from ppu_intrinics.h --
- */
-
-
-void
-gc_jd_stack_init(gc_jd_stack_t *stack)
-{
- stack->top = 0;
-}
-
-
-#ifdef __powerpc64__ // 64-bit mode
-
-void
-gc_jd_stack_push(gc_jd_stack_t *stack, gc_job_desc_t *item)
-{
- gc_eaddr_t top;
- gc_eaddr_t item_ea = ptr_to_ea(item);
- unsigned int done;
-
- do {
- top = __ldarx(&stack->top);
- item->sys.next = top;
- smp_wmb(); // order store of item->next before store of stack->top
- done = __stdcx(&stack->top, item_ea);
- } while (unlikely(done == 0));
-}
-
-gc_job_desc_t *
-gc_jd_stack_pop(gc_jd_stack_t *stack)
-{
- gc_eaddr_t s;
- gc_eaddr_t t;
- unsigned int done;
-
- do {
- s = __ldarx(&stack->top);
- if (s == 0) /* stack's empty */
- return 0;
- t = ((gc_job_desc_t *) ea_to_ptr(s))->sys.next;
- done = __stdcx(&stack->top, t);
- } while (unlikely(done == 0));
-
- return ea_to_ptr(s);
-}
-
-#else // 32-bit mode
-
-/*
- * In 32-bit mode, gc_eaddr's will have the top 32-bits zero.
- * The ldarx/stdcx instructions aren't available in 32-bit mode,
- * thus we use lwarx/stwcx on the low 32-bits of the 64-bit addresses.
- * Since we're big-endian, the low 32-bits are at word offset 1.
- */
-void
-gc_jd_stack_push(gc_jd_stack_t *stack, gc_job_desc_t *item)
-{
- gc_eaddr_t top;
- unsigned int done;
-
- do {
- top = __lwarx((int32_t *)(&stack->top) + 1);
- item->sys.next = top;
- smp_wmb(); // order store of item->sys.next before store of stack->top
- done = __stwcx((int32_t *)(&stack->top) + 1, item);
- } while (unlikely(done == 0));
-}
-
-gc_job_desc_t *
-gc_jd_stack_pop(gc_jd_stack_t *stack)
-{
- gc_eaddr_t s;
- gc_eaddr_t t;
- unsigned int done;
-
- do {
- s = __lwarx((int32_t *)(&stack->top) + 1);
- if (s == 0) /* stack's empty */
- return 0;
- t = ((gc_job_desc_t *) ea_to_ptr(s))->sys.next;
- done = __stwcx((int32_t *)(&stack->top) + 1, (uint32_t) t);
- } while (unlikely(done == 0));
-
- return ea_to_ptr(s);
-}
-
-#endif
diff --git a/gcell/lib/runtime/gc_job_manager.cc b/gcell/lib/runtime/gc_job_manager.cc
deleted file mode 100644
index d96bc5381..000000000
--- a/gcell/lib/runtime/gc_job_manager.cc
+++ /dev/null
@@ -1,186 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007,2008 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <gcell/gc_job_manager.h>
-#include "gc_job_manager_impl.h"
-#include <boost/weak_ptr.hpp>
-#include <stdio.h>
-
-
-static boost::weak_ptr<gc_job_manager> s_singleton;
-
-
-// custom deleter of gc_job_desc allocated via alloc_job_desc_sptr
-class job_desc_deleter {
- gc_job_manager_sptr d_mgr;
-public:
- job_desc_deleter(gc_job_manager_sptr mgr) : d_mgr(mgr) {}
-
- void operator()(gc_job_desc *jd) {
- d_mgr->free_job_desc(jd);
- }
-};
-
-
-
-gc_job_manager_sptr
-gc_make_job_manager(const gc_jm_options *options)
-{
- return gc_job_manager_sptr(new gc_job_manager_impl(options));
-}
-
-gc_job_manager::gc_job_manager(const gc_jm_options *options)
-{
- // nop
-}
-
-gc_job_manager::~gc_job_manager()
-{
- // nop
-}
-
-void
-gc_job_manager::set_debug(int debug)
-{
- // nop
-}
-
-int
-gc_job_manager::debug()
-{
- return 0;
-}
-
-void
-gc_job_manager::set_singleton(gc_job_manager_sptr mgr)
-{
- s_singleton = mgr;
-}
-
-gc_job_manager_sptr
-gc_job_manager::singleton()
-{
- return gc_job_manager_sptr(s_singleton);
-}
-
-gc_job_desc_sptr
-gc_job_manager::make_jd_sptr(gc_job_manager_sptr mgr, gc_job_desc *jd)
-{
- return gc_job_desc_sptr(jd, job_desc_deleter(mgr));
-}
-
-gc_job_desc_sptr
-gc_job_manager::alloc_job_desc(gc_job_manager_sptr mgr)
-{
- return make_jd_sptr(mgr, mgr->alloc_job_desc());
-}
-
-
-// ------------------------------------------------------------------------
-
-
-// custom deleter
-class spe_program_handle_deleter {
-public:
- void operator()(spe_program_handle_t *program) {
- if (program){
- int r = spe_image_close(program);
- if (r != 0){
- perror("spe_image_close");
- }
- }
- }
-};
-
-// nop custom deleter
-class nop_spe_program_handle_deleter {
-public:
- void operator()(spe_program_handle_t *program) {
- }
-};
-
-spe_program_handle_sptr
-gc_program_handle_from_filename(const std::string &filename)
-{
- return spe_program_handle_sptr(spe_image_open(filename.c_str()),
- spe_program_handle_deleter());
-}
-
-
-spe_program_handle_sptr
-gc_program_handle_from_address(spe_program_handle_t *handle)
-{
- return spe_program_handle_sptr(handle, nop_spe_program_handle_deleter());
-}
-
-const std::string
-gc_job_status_string(gc_job_status_t status)
-{
- switch(status){
- case JS_OK: return "JS_OK";
- case JS_SHUTTING_DOWN: return "JS_SHUTTING_DOWN";
- case JS_TOO_MANY_CLIENTS: return "JS_TOO_MANY_CLIENTS";
- case JS_UNKNOWN_PROC: return "JS_UNKNOWN_PROC";
- case JS_BAD_DIRECTION: return "JS_BAD_DIRECTION";
- case JS_BAD_EAH: return "JS_BAD_EAH";
- case JS_BAD_N_DIRECT: return "JS_BAD_N_DIRECT";
- case JS_BAD_N_EA: return "JS_BAD_N_EA";
- case JS_ARGS_TOO_LONG: return "JS_ARGS_TOO_LONG";
- case JS_BAD_JUJU: return "JS_BAD_JUJU";
- case JS_BAD_JOB_DESC: return "JS_BAD_JOB_DESC";
- default:
- char buf[100];
- snprintf(buf, sizeof(buf), "unknown gc_job_status_t (%d)\n", status);
- return buf;
- }
-}
-
-/*
- * exception classes
- */
-
-gc_exception::gc_exception(const std::string &msg)
- : runtime_error(msg)
-{
-}
-
-gc_unknown_proc::gc_unknown_proc(const std::string &msg)
- : gc_exception("gc_unknown_proc: " + msg)
-{
-}
-
-gc_bad_alloc::gc_bad_alloc(const std::string &msg)
- : gc_exception("gc_bad_alloc: " + msg)
-{
-}
-
-gc_bad_align::gc_bad_align(const std::string &msg)
- : gc_exception("gc_bad_align: " + msg)
-{
-}
-
-gc_bad_submit::gc_bad_submit(const std::string &name, gc_job_status_t status)
- : gc_exception("gc_bad_submit(" + name + "): " + gc_job_status_string(status))
-{
-}
diff --git a/gcell/lib/runtime/gc_job_manager_impl.cc b/gcell/lib/runtime/gc_job_manager_impl.cc
deleted file mode 100644
index 58597cf27..000000000
--- a/gcell/lib/runtime/gc_job_manager_impl.cc
+++ /dev/null
@@ -1,1404 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007,2008,2009,2010 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "gc_job_manager_impl.h"
-#include <gcell/gc_mbox.h>
-#include <gcell/gc_aligned_alloc.h>
-#include <gcell/memory_barrier.h>
-#include <gc_proc_def_utils.h>
-#include <atomic_dec_if_positive.h>
-#include <stdio.h>
-#include <stdexcept>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sched.h>
-
-typedef boost::unique_lock<boost::mutex> scoped_lock;
-
-#define __nop() __asm__ volatile ("ori 0,0,0" : : : "memory")
-#define __cctpl() __asm__ volatile ("or 1,1,1" : : : "memory")
-#define __cctpm() __asm__ volatile ("or 2,2,2" : : : "memory")
-#define __cctph() __asm__ volatile ("or 3,3,3" : : : "memory")
-#define __db8cyc() __asm__ volatile ("or 28,28,28" : : : "memory")
-#define __db10cyc() __asm__ volatile ("or 29,29,29" : : : "memory")
-#define __db12cyc() __asm__ volatile ("or 30,30,30" : : : "memory")
-#define __db16cyc() __asm__ volatile ("or 31,31,31" : : : "memory")
-
-
-#if 1
-#define CCTPL() __cctpl()
-#define CCTPM() __cctpm()
-#else
-#define CCTPL() (void) 0
-#define CCTPM() (void) 0
-#endif
-
-static const size_t CACHE_LINE_SIZE = 128;
-
-static const unsigned int DEFAULT_MAX_JOBS = 128;
-static const unsigned int DEFAULT_MAX_CLIENT_THREADS = 64;
-
-// FIXME this really depends on the SPU code...
-static const unsigned int MAX_TOTAL_INDIRECT_LENGTH = 16 * 1024;
-
-
-static bool s_key_initialized = false;
-static pthread_key_t s_client_key;
-
-static int s_worker_debug = 0;
-
-// custom deleter of gang_contexts for use with boost::shared_ptr
-class gang_deleter {
-public:
- void operator()(spe_gang_context_ptr_t ctx) {
- if (ctx){
- int r = spe_gang_context_destroy(ctx);
- if (r != 0){
- perror("spe_gang_context_destroy");
- }
- }
- }
-};
-
-
-// custom deleter of anything that can be freed with "free"
-class free_deleter {
-public:
- void operator()(void *p) {
- free(p);
- }
-};
-
-
-/*
- * Called when client thread is destroyed.
- * We mark our client info free.
- */
-static void
-client_key_destructor(void *p)
-{
- ((gc_client_thread_info *) p)->d_free = 1;
-}
-
-static bool
-is_power_of_2(uint32_t x)
-{
- return (x != 0) && !(x & (x - 1));
-}
-
-////////////////////////////////////////////////////////////////////////
-
-
-gc_job_manager_impl::gc_job_manager_impl(const gc_jm_options *options)
- : d_debug(0), d_spu_args(0),
- d_eh_cond(), d_eh_thread(0), d_eh_state(EHS_INIT),
- d_shutdown_requested(false),
- d_jc_cond(), d_jc_thread(0), d_jc_state(JCS_INIT), d_jc_njobs_active(0),
- d_ntell(0), d_tell_start(0),
- d_client_thread(0), d_ea_args_maxsize(0),
- d_proc_def(0), d_proc_def_ls_addr(0), d_nproc_defs(0)
-{
- if (!s_key_initialized){
- int r = pthread_key_create(&s_client_key, client_key_destructor);
- if (r != 0)
- throw std::runtime_error("pthread_key_create");
- s_key_initialized = true;
- }
-
- // ensure it's zero
- pthread_setspecific(s_client_key, 0);
-
- if (options != 0)
- d_options = *options;
-
- // provide the real default for those indicated with a zero
- if (d_options.max_jobs == 0)
- d_options.max_jobs = DEFAULT_MAX_JOBS;
- if (d_options.max_client_threads == 0)
- d_options.max_client_threads = DEFAULT_MAX_CLIENT_THREADS;
-
- if (!d_options.program_handle){
- fprintf(stderr, "gc_job_manager: options->program_handle must be non-zero\n");
- throw std::runtime_error("gc_job_manager: options->program_handle must be non-zero");
- }
-
- int ncpu_nodes = spe_cpu_info_get(SPE_COUNT_PHYSICAL_CPU_NODES, -1);
- int nusable_spes = spe_cpu_info_get(SPE_COUNT_USABLE_SPES, -1);
-
- if (debug()){
- printf("cpu_nodes = %d\n", ncpu_nodes);
- for (int i = 0; i < ncpu_nodes; i++){
- printf("node[%d].physical_spes = %2d\n", i,
- spe_cpu_info_get(SPE_COUNT_PHYSICAL_SPES, i));
- printf("node[%d].usable_spes = %2d\n", i,
- spe_cpu_info_get(SPE_COUNT_USABLE_SPES, i));
- }
- }
-
- // clamp nspes
- d_options.nspes = std::min(d_options.nspes, (unsigned int) MAX_SPES);
- nusable_spes = std::min(nusable_spes, (int) MAX_SPES);
-
- //
- // sanity check requested number of spes.
- //
- if (d_options.nspes == 0) // use all of them
- d_options.nspes = nusable_spes;
- else {
- if (d_options.nspes > (unsigned int) nusable_spes){
- fprintf(stderr,
- "gc_job_manager: warning: caller requested %d spes. There are only %d available.\n",
- d_options.nspes, nusable_spes);
- if (d_options.gang_schedule){
- // If we're gang scheduling we'll never get scheduled if we
- // ask for more than are available.
- throw std::out_of_range("gang_scheduling: not enough spes available");
- }
- else { // FIXME clamp to usable. problem on PS3 when overcommited
- fprintf(stderr, "gc_job_manager: clamping nspes to %d\n", nusable_spes);
- d_options.nspes = nusable_spes;
- }
- }
- }
-
- if (d_options.use_affinity){
- printf("gc_job_manager: warning: affinity request was ignored\n");
- }
-
- if (d_options.gang_schedule){
- d_gang = spe_gang_context_sptr(spe_gang_context_create(0), gang_deleter());
- if (!d_gang){
- perror("gc_job_manager_impl[spe_gang_context_create]");
- throw std::runtime_error("spe_gang_context_create");
- }
- }
-
- d_ntell = std::min(d_options.nspes, 2U);
-
- // ----------------------------------------------------------------
- // initalize the job queue
-
- d_queue = (gc_jd_queue_t *) gc_aligned_alloc(sizeof(gc_jd_queue_t), CACHE_LINE_SIZE);
- _d_queue_boost =
- boost::shared_ptr<void>((void *) d_queue, free_deleter());
- gc_jd_queue_init(d_queue);
-
-
- // ----------------------------------------------------------------
- // create the spe contexts
-
- // 1 spu_arg struct for each SPE
- assert(sizeof(gc_spu_args_t) % 16 == 0);
- d_spu_args =
- (gc_spu_args_t *) gc_aligned_alloc(MAX_SPES * sizeof(gc_spu_args_t), 16);
- _d_spu_args_boost =
- boost::shared_ptr<void>((void *) d_spu_args, free_deleter());
-
- // 2 completion info structs for each SPE (we double buffer them)
- assert(sizeof(gc_comp_info_t) % CACHE_LINE_SIZE == 0);
- d_comp_info =
- (gc_comp_info_t *) gc_aligned_alloc(2 * MAX_SPES * sizeof(gc_comp_info_t),
- CACHE_LINE_SIZE);
- _d_comp_info_boost =
- boost::shared_ptr<void>((void *) d_comp_info, free_deleter());
-
-
- // get a handle to the spe program
-
- spe_program_handle_t *spe_image = d_options.program_handle.get();
-
- // fish proc_def table out of SPE ELF file
-
- if (!gcpd_find_table(spe_image, &d_proc_def, &d_nproc_defs, &d_proc_def_ls_addr)){
- fprintf(stderr, "gc_job_manager_impl: couldn't find gc_proc_defs in SPE ELF file.\n");
- throw std::runtime_error("no gc_proc_defs");
- }
- // fprintf(stderr, "d_proc_def_ls_addr = 0x%0x\n", d_proc_def_ls_addr);
-
- int spe_flags = (SPE_EVENTS_ENABLE
- | SPE_MAP_PS
- | SPE_CFG_SIGNOTIFY1_OR
- | SPE_CFG_SIGNOTIFY2_OR);
-
- for (unsigned int i = 0; i < d_options.nspes; i++){
- // FIXME affinity stuff goes here
- d_worker[i].spe_ctx = spe_context_create(spe_flags, d_gang.get());;
- if (d_worker[i].spe_ctx == 0){
- perror("spe_context_create");
- throw std::runtime_error("spe_context_create");
- }
-
- d_worker[i].spe_ctrl =
- (spe_spu_control_area_t *)spe_ps_area_get(d_worker[i].spe_ctx, SPE_CONTROL_AREA);
- if (d_worker[i].spe_ctrl == 0){
- perror("spe_ps_area_get(SPE_CONTROL_AREA)");
- throw std::runtime_error("spe_ps_area_get(SPE_CONTROL_AREA)");
- }
-
- d_worker[i].spe_idx = i;
- d_worker[i].spu_args = &d_spu_args[i];
- d_worker[i].spu_args->queue = ptr_to_ea(d_queue);
- d_worker[i].spu_args->comp_info[0] = ptr_to_ea(&d_comp_info[2*i+0]);
- d_worker[i].spu_args->comp_info[1] = ptr_to_ea(&d_comp_info[2*i+1]);
- d_worker[i].spu_args->spu_idx = i;
- d_worker[i].spu_args->nspus = d_options.nspes;
- d_worker[i].spu_args->proc_def_ls_addr = d_proc_def_ls_addr;
- d_worker[i].spu_args->nproc_defs = d_nproc_defs;
- d_worker[i].spu_args->log.base = 0;
- d_worker[i].spu_args->log.nentries = 0;
- d_worker[i].state = WS_INIT;
-
- int r = spe_program_load(d_worker[i].spe_ctx, spe_image);
- if (r != 0){
- perror("spe_program_load");
- throw std::runtime_error("spe_program_load");
- }
- }
-
- setup_logfiles();
-
- // ----------------------------------------------------------------
- // initalize the free list of job descriptors
-
- d_free_list = (gc_jd_stack_t *) gc_aligned_alloc(sizeof(gc_jd_stack_t), CACHE_LINE_SIZE);
- // This ensures that the memory associated with d_free_list is
- // automatically freed in the destructor or if an exception occurs
- // here in the constructor.
- _d_free_list_boost =
- boost::shared_ptr<void>((void *) d_free_list, free_deleter());
- gc_jd_stack_init(d_free_list);
-
- if (debug()){
- printf("sizeof(d_jd[0]) = %d (0x%x)\n", sizeof(d_jd[0]), sizeof(d_jd[0]));
- printf("max_jobs = %u\n", d_options.max_jobs);
- }
-
- // Initialize the array of job descriptors.
- d_jd = (gc_job_desc_t *) gc_aligned_alloc(sizeof(d_jd[0]) * d_options.max_jobs, CACHE_LINE_SIZE);
- _d_jd_boost = boost::shared_ptr<void>((void *) d_jd, free_deleter());
-
-
- // set unique job_id
- for (int i = 0; i < (int) d_options.max_jobs; i++)
- d_jd[i].sys.job_id = i;
-
- // push them onto the free list
- for (int i = d_options.max_jobs - 1; i >= 0; i--)
- free_job_desc(&d_jd[i]);
-
- // ----------------------------------------------------------------
- // initialize d_client_thread
-
- {
- gc_client_thread_info_sa cti(
- new gc_client_thread_info[d_options.max_client_threads]);
-
- d_client_thread.swap(cti);
-
- for (unsigned int i = 0; i < d_options.max_client_threads; i++)
- d_client_thread[i].d_client_id = i;
- }
-
- // ----------------------------------------------------------------
- // initialize bitvectors
-
- // initialize d_bvlen, the number of longs in job related bitvectors.
- int bits_per_long = sizeof(unsigned long) * 8;
- d_bvlen = (d_options.max_jobs + bits_per_long - 1) / bits_per_long;
-
- // allocate all bitvectors in a single cache-aligned chunk
- size_t nlongs = d_bvlen * d_options.max_client_threads;
- void *p = gc_aligned_alloc(nlongs * sizeof(unsigned long), CACHE_LINE_SIZE);
- _d_all_bitvectors = boost::shared_ptr<void>(p, free_deleter());
-
- // Now point the gc_client_thread_info bitvectors into this storage
- unsigned long *v = (unsigned long *) p;
-
- for (unsigned int i = 0; i < d_options.max_client_threads; i++, v += d_bvlen)
- d_client_thread[i].d_jobs_done = v;
-
-
- // ----------------------------------------------------------------
- // create the spe event handler & worker (SPE) threads
-
- create_event_handler();
-}
-
-////////////////////////////////////////////////////////////////////////
-
-gc_job_manager_impl::~gc_job_manager_impl()
-{
- shutdown();
-
- d_jd = 0; // handled via _d_jd_boost
- d_free_list = 0; // handled via _d_free_list_boost
- d_queue = 0; // handled via _d_queue_boost
-
- // clear cti, since we've deleted the underlying data
- pthread_setspecific(s_client_key, 0);
-
- unmap_logfiles();
-}
-
-bool
-gc_job_manager_impl::shutdown()
-{
- scoped_lock l(d_eh_mutex);
-
- {
- scoped_lock l2(d_jc_mutex);
- d_shutdown_requested = true; // set flag for event handler thread
- d_jc_cond.notify_one(); // wake up job completer
- }
-
- // should only happens during early QA code
- if (d_eh_thread == 0 && d_eh_state == EHS_INIT)
- return false;
-
- while (d_eh_state != EHS_DEAD) // wait for it to finish
- d_eh_cond.wait(l);
-
- return true;
-}
-
-int
-gc_job_manager_impl::nspes() const
-{
- return d_options.nspes;
-}
-
-////////////////////////////////////////////////////////////////////////
-
-void
-gc_job_manager_impl::bv_zero(unsigned long *bv)
-{
- memset(bv, 0, sizeof(unsigned long) * d_bvlen);
-}
-
-inline void
-gc_job_manager_impl::bv_clr(unsigned long *bv, unsigned int bitno)
-{
- unsigned int wi = bitno / (sizeof (unsigned long) * 8);
- unsigned int bi = bitno & ((sizeof (unsigned long) * 8) - 1);
- bv[wi] &= ~(1UL << bi);
-}
-
-inline void
-gc_job_manager_impl::bv_set(unsigned long *bv, unsigned int bitno)
-{
- unsigned int wi = bitno / (sizeof (unsigned long) * 8);
- unsigned int bi = bitno & ((sizeof (unsigned long) * 8) - 1);
- bv[wi] |= (1UL << bi);
-}
-
-inline bool
-gc_job_manager_impl::bv_isset(unsigned long *bv, unsigned int bitno)
-{
- unsigned int wi = bitno / (sizeof (unsigned long) * 8);
- unsigned int bi = bitno & ((sizeof (unsigned long) * 8) - 1);
- return (bv[wi] & (1UL << bi)) != 0;
-}
-
-inline bool
-gc_job_manager_impl::bv_isclr(unsigned long *bv, unsigned int bitno)
-{
- unsigned int wi = bitno / (sizeof (unsigned long) * 8);
- unsigned int bi = bitno & ((sizeof (unsigned long) * 8) - 1);
- return (bv[wi] & (1UL << bi)) == 0;
-}
-
-////////////////////////////////////////////////////////////////////////
-
-gc_job_desc *
-gc_job_manager_impl::alloc_job_desc()
-{
- // stack is lock free, and safe to call from any thread
- gc_job_desc *jd = gc_jd_stack_pop(d_free_list);
- if (jd == 0)
- throw gc_bad_alloc("alloc_job_desc: none available");
-
- return jd;
-}
-
-void
-gc_job_manager_impl::free_job_desc(gc_job_desc *jd)
-{
- // stack is lock free, thus safe to call from any thread
- if (jd != 0)
- gc_jd_stack_push(d_free_list, jd);
-}
-
-////////////////////////////////////////////////////////////////////////
-
-
-inline bool
-gc_job_manager_impl::incr_njobs_active()
-{
- scoped_lock l(d_jc_mutex);
-
- if (d_shutdown_requested)
- return false;
-
- if (d_jc_njobs_active++ == 0) // signal on 0 to 1 transition
- d_jc_cond.notify_one();
-
- return true;
-}
-
-inline void
-gc_job_manager_impl::decr_njobs_active(int n)
-{
- scoped_lock l(d_jc_mutex);
- d_jc_njobs_active -= n;
-}
-
-
-/*
- * We check as much as we can here on the PPE side, so that the SPE
- * doesn't have to.
- */
-static bool
-check_direct_args(gc_job_desc *jd, gc_job_direct_args *args)
-{
- if (args->nargs > MAX_ARGS_DIRECT){
- jd->status = JS_BAD_N_DIRECT;
- return false;
- }
-
- return true;
-}
-
-static bool
-check_ea_args(gc_job_desc *jd, gc_job_ea_args *p)
-{
- if (p->nargs > MAX_ARGS_EA){
- jd->status = JS_BAD_N_EA;
- return false;
- }
-
- uint32_t dir_union = 0;
-
- for (unsigned int i = 0; i < p->nargs; i++){
- dir_union |= p->arg[i].direction;
- switch(p->arg[i].direction){
- case GCJD_DMA_GET:
- case GCJD_DMA_PUT:
- break;
-
- default:
- jd->status = JS_BAD_DIRECTION;
- return false;
- }
- }
-
- if (p->nargs > 1){
- unsigned int common_eah = (p->arg[0].ea_addr) >> 32;
- for (unsigned int i = 1; i < p->nargs; i++){
- if ((p->arg[i].ea_addr >> 32) != common_eah){
- jd->status = JS_BAD_EAH;
- return false;
- }
- }
- }
-
- jd->sys.direction_union = dir_union;
- return true;
-}
-
-bool
-gc_job_manager_impl::submit_job(gc_job_desc *jd)
-{
- // Ensure it's one of our job descriptors
-
- if (jd < d_jd || jd >= &d_jd[d_options.max_jobs]){
- jd->status = JS_BAD_JOB_DESC;
- return false;
- }
-
- // Ensure we've got a client_thread_info assigned to this thread.
-
- gc_client_thread_info *cti =
- (gc_client_thread_info *) pthread_getspecific(s_client_key);
- if (unlikely(cti == 0)){
- if ((cti = alloc_cti()) == 0){
- fprintf(stderr, "gc_job_manager_impl::submit_job: Too many client threads.\n");
- jd->status = JS_TOO_MANY_CLIENTS;
- return false;
- }
- int r = pthread_setspecific(s_client_key, cti);
- if (r != 0){
- jd->status = JS_BAD_JUJU;
- fprintf(stderr, "pthread_setspecific failed (return = %d)\n", r);
- return false;
- }
- }
-
- if (jd->proc_id == GCP_UNKNOWN_PROC){
- jd->status = JS_UNKNOWN_PROC;
- return false;
- }
-
- if (!check_direct_args(jd, &jd->input))
- return false;
-
- if (!check_direct_args(jd, &jd->output))
- return false;
-
- if (!check_ea_args(jd, &jd->eaa))
- return false;
-
- jd->status = JS_OK;
- jd->sys.client_id = cti->d_client_id;
-
- if (!incr_njobs_active()){
- jd->status = JS_SHUTTING_DOWN;
- return false;
- }
-
- gc_jd_queue_enqueue(d_queue, jd);
- // tell_spes_to_check_queue();
- return true;
-}
-
-bool
-gc_job_manager_impl::wait_job(gc_job_desc *jd)
-{
- bool done;
- return wait_jobs(1, &jd, &done, GC_WAIT_ANY) == 1 && jd->status == JS_OK;
-}
-
-int
-gc_job_manager_impl::wait_jobs(unsigned int njobs,
- gc_job_desc *jd[],
- bool done[],
- gc_wait_mode mode)
-{
- unsigned int i;
-
- gc_client_thread_info *cti =
- (gc_client_thread_info *) pthread_getspecific(s_client_key);
- if (unlikely(cti == 0))
- return -1;
-
- for (i = 0; i < njobs; i++){
- done[i] = false;
- if (unlikely(jd[i]->sys.client_id != cti->d_client_id)){
- fprintf(stderr, "gc_job_manager_impl::wait_jobs: can't wait for a job you didn't submit\n");
- return -1;
- }
- }
-
- {
- scoped_lock l(cti->d_mutex);
-
- // setup info for event handler
- cti->d_state = (mode == GC_WAIT_ANY) ? CT_WAIT_ANY : CT_WAIT_ALL;
- cti->d_njobs_waiting_for = njobs;
- cti->d_jobs_waiting_for = jd;
- assert(cti->d_jobs_done != 0);
-
- unsigned int ndone = 0;
-
- // wait for jobs to complete
-
- while (1){
- ndone = 0;
- for (i= 0; i < njobs; i++){
- if (done[i])
- ndone++;
- else if (bv_isset(cti->d_jobs_done, jd[i]->sys.job_id)){
- bv_clr(cti->d_jobs_done, jd[i]->sys.job_id);
- done[i] = true;
- ndone++;
- }
- }
-
- if (mode == GC_WAIT_ANY && ndone > 0)
- break;
-
- if (mode == GC_WAIT_ALL && ndone == njobs)
- break;
-
- // FIXME what happens when somebody calls shutdown?
-
- cti->d_cond.wait(l); // wait for event handler to wake us up
- }
-
- cti->d_state = CT_NOT_WAITING;
- cti->d_njobs_waiting_for = 0; // tidy up (not reqd)
- cti->d_jobs_waiting_for = 0; // tidy up (not reqd)
- return ndone;
- }
-}
-
-////////////////////////////////////////////////////////////////////////
-
-bool
-gc_job_manager_impl::send_all_spes(uint32_t msg)
-{
- bool ok = true;
-
- for (unsigned int i = 0; i < d_options.nspes; i++)
- ok &= send_spe(i, msg);
-
- return ok;
-}
-
-bool
-gc_job_manager_impl::send_spe(unsigned int spe, uint32_t msg)
-{
- if (spe >= d_options.nspes)
- return false;
-
- int r = spe_in_mbox_write(d_worker[spe].spe_ctx, &msg, 1,
- SPE_MBOX_ALL_BLOCKING);
- if (r < 0){
- perror("spe_in_mbox_write");
- return false;
- }
-
- return r == 1;
-}
-
-void
-gc_job_manager_impl::tell_spes_to_check_queue()
-{
- int nspes = d_options.nspes;
-
- for (int i = 0, ntold = 0; ntold < d_ntell && i < nspes ; ++i){
- volatile spe_spu_control_area_t *spe_ctrl = d_worker[d_tell_start].spe_ctrl;
- int nfree = (spe_ctrl->SPU_Mbox_Stat >> 8) & 0xFF;
- if (nfree == 4){
- spe_ctrl->SPU_In_Mbox = MK_MBOX_MSG(OP_CHECK_QUEUE, 0);
- ntold++;
- }
-
- unsigned int t = d_tell_start + 1;
- if (t >= d_options.nspes)
- t = 0;
- d_tell_start = t;
- }
-}
-
-
-////////////////////////////////////////////////////////////////////////
-
-static void
-pthread_create_failure_msg(int r, const char *which)
-{
- char buf[256];
- const char *s = 0;
-
- switch (r){
- case EAGAIN: s = "EAGAIN"; break;
- case EINVAL: s = "EINVAL"; break;
- case EPERM: s = "EPERM"; break;
- default:
- snprintf(buf, sizeof(buf), "Unknown error %d", r);
- s = buf;
- break;
- }
- fprintf(stderr, "pthread_create[%s] failed: %s\n", which, s);
-}
-
-
-static bool
-start_thread(pthread_t *thread,
- void *(*start_routine)(void *), void *arg,
- const char *msg)
-{
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
- // FIXME save sigprocmask
- // FIXME set sigprocmask
-
- int r = pthread_create(thread, &attr, start_routine, arg);
-
- // FIXME restore sigprocmask
-
- if (r != 0){
- pthread_create_failure_msg(r, msg);
- return false;
- }
- return true;
-}
-
-
-////////////////////////////////////////////////////////////////////////
-
-static void *start_worker(void *arg);
-
-static void *
-start_event_handler(void *arg)
-{
- gc_job_manager_impl *p = (gc_job_manager_impl *) arg;
- p->event_handler_loop();
- return 0;
-}
-
-static void *
-start_job_completer(void *arg)
-{
- gc_job_manager_impl *p = (gc_job_manager_impl *) arg;
- p->job_completer_loop();
- return 0;
-}
-
-void
-gc_job_manager_impl::create_event_handler()
-{
- // create the SPE event handler and register our interest in events
-
- d_spe_event_handler.ptr = spe_event_handler_create();
- if (d_spe_event_handler.ptr == 0){
- perror("spe_event_handler_create");
- throw std::runtime_error("spe_event_handler_create");
- }
-
- for (unsigned int i = 0; i < d_options.nspes; i++){
- spe_event_unit_t eu;
- memset(&eu, 0, sizeof(eu));
- eu.events = SPE_EVENT_OUT_INTR_MBOX | SPE_EVENT_SPE_STOPPED;
- eu.spe = d_worker[i].spe_ctx;
- eu.data.u32 = i; // set in events returned by spe_event_wait
-
- if (spe_event_handler_register(d_spe_event_handler.ptr, &eu) != 0){
- perror("spe_event_handler_register");
- throw std::runtime_error("spe_event_handler_register");
- }
- }
-
- // create the event handling thread
-
- if (!start_thread(&d_eh_thread, start_event_handler, this, "event_handler")){
- throw std::runtime_error("pthread_create");
- }
-
- // create the job completion thread
-
- if (!start_thread(&d_jc_thread, start_job_completer, this, "job_completer")){
- throw std::runtime_error("pthread_create");
- }
-
- // create the SPE worker threads
-
- bool ok = true;
- for (unsigned int i = 0; ok && i < d_options.nspes; i++){
- char name[256];
- snprintf(name, sizeof(name), "worker[%d]", i);
- ok &= start_thread(&d_worker[i].thread, start_worker,
- &d_worker[i], name);
- }
-
- if (!ok){
- //
- // FIXME Clean up the mess. Need to terminate event handler and all workers.
- //
- // this should cause the workers to exit, unless they're seriously broken
- send_all_spes(MK_MBOX_MSG(OP_EXIT, 0));
-
- shutdown();
-
- throw std::runtime_error("pthread_create");
- }
-}
-
-////////////////////////////////////////////////////////////////////////
-
-void
-gc_job_manager_impl::set_eh_state(evt_handler_state s)
-{
- scoped_lock l(d_eh_mutex);
- d_eh_state = s;
- d_eh_cond.notify_all();
-}
-
-void
-gc_job_manager_impl::set_ea_args_maxsize(int maxsize)
-{
- scoped_lock l(d_eh_mutex);
- d_ea_args_maxsize = maxsize;
- d_eh_cond.notify_all();
-}
-
-void
-gc_job_manager_impl::print_event(spe_event_unit_t *evt)
-{
- printf("evt: spe = %d events = (0x%x)", evt->data.u32, evt->events);
-
- if (evt->events & SPE_EVENT_OUT_INTR_MBOX)
- printf(" OUT_INTR_MBOX");
-
- if (evt->events & SPE_EVENT_IN_MBOX)
- printf(" IN_MBOX");
-
- if (evt->events & SPE_EVENT_TAG_GROUP)
- printf(" TAG_GROUP");
-
- if (evt->events & SPE_EVENT_SPE_STOPPED)
- printf(" SPE_STOPPED");
-
- printf("\n");
-}
-
-struct job_client_info {
- uint16_t job_id;
- uint16_t client_id;
-};
-
-static int
-compare_jci_clients(const void *va, const void *vb)
-{
- const job_client_info *a = (job_client_info *) va;
- const job_client_info *b = (job_client_info *) vb;
-
- return a->client_id - b->client_id;
-}
-
-void
-gc_job_manager_impl::notify_clients_jobs_are_done(unsigned int spe_num,
- unsigned int completion_info_idx)
-{
- const char *msg = "gc_job_manager_impl::notify_client_job_is_done (INTERNAL ERROR)";
-
- smp_rmb(); // order reads so we know that data sent from SPE is here
-
- gc_comp_info_t *ci = &d_comp_info[2 * spe_num + (completion_info_idx & 0x1)];
-
- if (ci->ncomplete == 0){ // never happens, but ensures code below is correct
- ci->in_use = 0;
- return;
- }
-
- decr_njobs_active(ci->ncomplete);
-
- if (0){
- static int total_jobs;
- static int total_msgs;
- total_msgs++;
- total_jobs += ci->ncomplete;
- printf("ppe: tj = %6d tm = %6d\n", total_jobs, total_msgs);
- }
-
- job_client_info gci[GC_CI_NJOBS];
-
- /*
- * Make one pass through and sanity check everything while filling in gci
- */
- for (unsigned int i = 0; i < ci->ncomplete; i++){
- unsigned int job_id = ci->job_id[i];
-
- if (job_id >= d_options.max_jobs){
- // internal error, shouldn't happen
- fprintf(stderr,"%s: invalid job_id = %d\n", msg, job_id);
- ci->in_use = 0; // clear flag so SPE knows we're done with it
- return;
- }
- gc_job_desc *jd = &d_jd[job_id];
-
- if (jd->sys.client_id >= d_options.max_client_threads){
- // internal error, shouldn't happen
- fprintf(stderr, "%s: invalid client_id = %d\n", msg, jd->sys.client_id);
- ci->in_use = 0; // clear flag so SPE knows we're done with it
- return;
- }
-
- gci[i].job_id = job_id;
- gci[i].client_id = jd->sys.client_id;
- }
-
- // sort by client_id so we only have to lock & signal once / client
-
- if (ci->ncomplete > 1)
- qsort(gci, ci->ncomplete, sizeof(gci[0]), compare_jci_clients);
-
- // "wind-in"
-
- gc_client_thread_info *last_cti = &d_client_thread[gci[0].client_id];
- last_cti->d_mutex.lock();
- bv_set(last_cti->d_jobs_done, gci[0].job_id); // mark job done
-
- for (unsigned int i = 1; i < ci->ncomplete; i++){
-
- gc_client_thread_info *cti = &d_client_thread[gci[i].client_id];
-
- if (cti != last_cti){ // new client?
-
- // yes. signal old client, unlock old, lock new
-
- // FIXME we could distinguish between CT_WAIT_ALL & CT_WAIT_ANY
-
- if (last_cti->d_state == CT_WAIT_ANY || last_cti->d_state == CT_WAIT_ALL)
- last_cti->d_cond.notify_one(); // wake client thread up
-
- last_cti->d_mutex.unlock();
- cti->d_mutex.lock();
- last_cti = cti;
- }
-
- // mark job done
- bv_set(cti->d_jobs_done, gci[i].job_id);
- }
-
- // "wind-out"
-
- if (last_cti->d_state == CT_WAIT_ANY || last_cti->d_state == CT_WAIT_ALL)
- last_cti->d_cond.notify_one(); // wake client thread up
- last_cti->d_mutex.unlock();
-
- ci->in_use = 0; // clear flag so SPE knows we're done with it
-}
-
-void
-gc_job_manager_impl::handle_event(spe_event_unit_t *evt)
-{
- // print_event(evt);
-
- int spe_num = evt->data.u32;
-
- // only a single event type can be signaled at a time
-
- if (evt->events == SPE_EVENT_OUT_INTR_MBOX) { // SPE sent us 1 or more msgs
- static const int NMSGS = 32;
- unsigned int msg[NMSGS];
- int n = spe_out_intr_mbox_read(evt->spe, msg, NMSGS, SPE_MBOX_ANY_BLOCKING);
- // printf("spe_out_intr_mbox_read = %d\n", n);
- if (n < 0){
- perror("spe_out_intr_mbox_read");
- }
- else {
- for (int i = 0; i < n; i++){
- switch(MBOX_MSG_OP(msg[i])){
-#if 0
- case OP_JOBS_DONE:
- if (debug())
- printf("eh: job_done (0x%08x) from spu[%d]\n", msg[i], spe_num);
- notify_clients_jobs_are_done(spe_num, MBOX_MSG_ARG(msg[i]));
- break;
-#endif
- case OP_SPU_BUFSIZE:
- set_ea_args_maxsize(MBOX_MSG_ARG(msg[i]));
- break;
-
- case OP_EXIT:
- default:
- printf("eh: Unexpected msg (0x%08x) from spu[%d]\n", msg[i], spe_num);
- break;
- }
- }
- }
- }
- else if (evt->events == SPE_EVENT_SPE_STOPPED){ // the SPE stopped
- spe_stop_info_t si;
- int r = spe_stop_info_read(evt->spe, &si);
- if (r < 0){
- perror("spe_stop_info_read");
- }
- else {
- switch (si.stop_reason){
- case SPE_EXIT:
- if (debug()){
- printf("eh: spu[%d] SPE_EXIT w/ exit_code = %d\n",
- spe_num, si.result.spe_exit_code);
- }
- break;
- case SPE_STOP_AND_SIGNAL:
- printf("eh: spu[%d] SPE_STOP_AND_SIGNAL w/ spe_signal_code = 0x%x\n",
- spe_num, si.result.spe_signal_code);
- break;
- case SPE_RUNTIME_ERROR:
- printf("eh: spu[%d] SPE_RUNTIME_ERROR w/ spe_runtime_error = 0x%x\n",
- spe_num, si.result.spe_runtime_error);
- break;
- case SPE_RUNTIME_EXCEPTION:
- printf("eh: spu[%d] SPE_RUNTIME_EXCEPTION w/ spe_runtime_exception = 0x%x\n",
- spe_num, si.result.spe_runtime_exception);
- break;
- case SPE_RUNTIME_FATAL:
- printf("eh: spu[%d] SPE_RUNTIME_FATAL w/ spe_runtime_fatal = 0x%x\n",
- spe_num, si.result.spe_runtime_fatal);
- break;
- case SPE_CALLBACK_ERROR:
- printf("eh: spu[%d] SPE_CALLBACK_ERROR w/ spe_callback_error = 0x%x\n",
- spe_num, si.result.spe_callback_error);
- break;
- case SPE_ISOLATION_ERROR:
- printf("eh: spu[%d] SPE_ISOLATION_ERROR w/ spe_isolation_error = 0x%x\n",
- spe_num, si.result.spe_isolation_error);
- break;
- default:
- printf("eh: spu[%d] UNKNOWN STOP REASON (%d) w/ spu_status = 0x%x\n",
- spe_num, si.stop_reason, si.spu_status);
- break;
- }
- }
- }
-#if 0 // not enabled
- else if (evt->events == SPE_EVENT_IN_MBOX){ // there's room to write to SPE
- // spe_in_mbox_write (ignore)
- }
- else if (evt->events == SPE_EVENT_TAG_GROUP){ // our DMA completed
- // spe_mfcio_tag_status_read
- }
-#endif
- else {
- fprintf(stderr, "handle_event: unexpected evt->events = 0x%x\n", evt->events);
- return;
- }
-}
-
-//
-// This is the "main program" of the event handling thread
-//
-void
-gc_job_manager_impl::event_handler_loop()
-{
- static const int MAX_EVENTS = 16;
- static const int TIMEOUT = 20; // how long to block in milliseconds
-
- spe_event_unit_t events[MAX_EVENTS];
-
- if (d_debug)
- printf("event_handler_loop: starting\n");
-
- set_eh_state(EHS_RUNNING);
-
- // ask the first spe for its max bufsize
- send_spe(0, MK_MBOX_MSG(OP_GET_SPU_BUFSIZE, 0));
-
- while (1){
- switch(d_eh_state){
-
- case EHS_RUNNING: // normal stuff
- if (d_shutdown_requested) {
- set_eh_state(EHS_SHUTTING_DOWN);
- }
- break;
-
- case EHS_SHUTTING_DOWN:
- if (d_jc_state == JCS_DEAD){
- send_all_spes(MK_MBOX_MSG(OP_EXIT, 0));
- set_eh_state(EHS_WAITING_FOR_WORKERS_TO_DIE);
- }
- break;
-
- case EHS_WAITING_FOR_WORKERS_TO_DIE:
- {
- bool all_dead = true;
- for (unsigned int i = 0; i < d_options.nspes; i++)
- all_dead &= d_worker[i].state == WS_DEAD;
-
- if (all_dead){
- set_eh_state(EHS_DEAD);
- if (d_debug)
- printf("event_handler_loop: exiting\n");
- return;
- }
- }
- break;
-
- default:
- set_eh_state(EHS_DEAD);
- printf("event_handler_loop(default): exiting\n");
- return;
- }
-
- // block waiting for events...
- int nevents = spe_event_wait(d_spe_event_handler.ptr,
- events, MAX_EVENTS, TIMEOUT);
- if (nevents < 0){
- perror("spe_wait_event");
- // FIXME bail?
- }
- for (int i = 0; i < nevents; i++){
- handle_event(&events[i]);
- }
- }
-}
-
-////////////////////////////////////////////////////////////////////////
-
-void
-gc_job_manager_impl::poll_for_job_completion()
-{
- static const int niter = 10000;
-
- CCTPL(); // change current (h/w) thread priority to low
-
- for (int n = 0; n < niter; n++){
-
- for (unsigned int spe_num = 0; spe_num < d_options.nspes; spe_num++){
- volatile spe_spu_control_area_t *spe_ctrl = d_worker[spe_num].spe_ctrl;
- int nentries = spe_ctrl->SPU_Mbox_Stat & 0xFF;
- while (nentries-- > 0){
- unsigned int msg = spe_ctrl->SPU_Out_Mbox;
- switch(MBOX_MSG_OP(msg)){
- case OP_JOBS_DONE:
- if (debug())
- printf("jc: job_done (0x%08x) from spu[%d]\n", msg, spe_num);
-
- CCTPM(); // change current thread priority to medium
- notify_clients_jobs_are_done(spe_num, MBOX_MSG_ARG(msg));
- CCTPL();
- break;
-
- default:
- printf("jc: Unexpected msg (0x%08x) from spu[%d]\n", msg, spe_num);
- break;
- }
- }
- }
- }
- CCTPM();
-}
-
-//
-// This is the "main program" of the job completer thread
-//
-void
-gc_job_manager_impl::job_completer_loop()
-{
- d_jc_state = JCS_RUNNING;
-
- while (1){
- {
- scoped_lock l(d_jc_mutex);
- if (d_jc_njobs_active == 0){
- if (d_shutdown_requested){
- d_jc_state = JCS_DEAD;
- return;
- }
- d_jc_cond.wait(l);
- }
- }
-
- poll_for_job_completion();
- }
-}
-
-////////////////////////////////////////////////////////////////////////
-// this is the top of the SPE worker threads
-
-static void *
-start_worker(void *arg)
-{
- worker_ctx *w = (worker_ctx *) arg;
- spe_stop_info_t si;
-
- w->state = WS_RUNNING;
- if (s_worker_debug)
- printf("worker[%d]: WS_RUNNING\n", w->spe_idx);
-
- unsigned int entry = SPE_DEFAULT_ENTRY;
- int r = spe_context_run(w->spe_ctx, &entry, 0, w->spu_args, 0, &si);
-
- if (r < 0){ // error
- char buf[64];
- snprintf(buf, sizeof(buf), "worker[%d]: spe_context_run", w->spe_idx);
- perror(buf);
- }
- else if (r == 0){
- // spe program called exit.
- if (s_worker_debug)
- printf("worker[%d]: SPE_EXIT w/ exit_code = %d\n",
- w->spe_idx, si.result.spe_exit_code);
- }
- else {
- // called stop_and_signal
- //
- // I'm not sure we'll ever get here. I think the event
- // handler will catch this...
- printf("worker[%d]: SPE_STOP_AND_SIGNAL w/ spe_signal_code = 0x%x\n",
- w->spe_idx, si.result.spe_signal_code);
- }
-
- // in any event, we're committing suicide now ;)
- if (s_worker_debug)
- printf("worker[%d]: WS_DEAD\n", w->spe_idx);
-
- w->state = WS_DEAD;
- return 0;
-}
-
-////////////////////////////////////////////////////////////////////////
-
-gc_client_thread_info *
-gc_job_manager_impl::alloc_cti()
-{
- for (unsigned int i = 0; i < d_options.max_client_threads; i++){
- if (d_client_thread[i].d_free){
- // try to atomically grab it
- if (_atomic_dec_if_positive(ptr_to_ea(&d_client_thread[i].d_free)) == 0){
- // got it...
- gc_client_thread_info *cti = &d_client_thread[i];
- cti->d_state = CT_NOT_WAITING;
- bv_zero(cti->d_jobs_done);
- cti->d_njobs_waiting_for = 0;
- cti->d_jobs_waiting_for = 0;
-
- return cti;
- }
- }
- }
- return 0;
-}
-
-void
-gc_job_manager_impl::free_cti(gc_client_thread_info *cti)
-{
- assert((size_t) (cti - d_client_thread.get()) < d_options.max_client_threads);
- cti->d_free = 1;
-}
-
-int
-gc_job_manager_impl::ea_args_maxsize()
-{
- scoped_lock l(d_eh_mutex);
-
- while (d_ea_args_maxsize == 0) // wait for it to be initialized
- d_eh_cond.wait(l);
-
- return d_ea_args_maxsize;
-}
-
-void
-gc_job_manager_impl::set_debug(int debug)
-{
- d_debug = debug;
- s_worker_debug = debug;
-}
-
-int
-gc_job_manager_impl::debug()
-{
- return d_debug;
-}
-
-////////////////////////////////////////////////////////////////////////
-
-void
-gc_job_manager_impl::setup_logfiles()
-{
- if (!d_options.enable_logging)
- return;
-
- if (d_options.log2_nlog_entries == 0)
- d_options.log2_nlog_entries = 12;
-
- // must end up a multiple of the page size
-
- size_t pagesize = getpagesize();
- size_t s = (1 << d_options.log2_nlog_entries) * sizeof(gc_log_entry_t);
- s = ((s + pagesize - 1) / pagesize) * pagesize;
- size_t nentries = s / sizeof(gc_log_entry_t);
- assert(is_power_of_2(nentries));
-
- for (unsigned int i = 0; i < d_options.nspes; i++){
- char filename[100];
- snprintf(filename, sizeof(filename), "spu_log.%02d", i);
- int fd = open(filename, O_CREAT|O_TRUNC|O_RDWR, 0664);
- if (fd == -1){
- perror(filename);
- return;
- }
- lseek(fd, s - 1, SEEK_SET);
- write(fd, "\0", 1);
- void *p = mmap(0, s, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
- if (p == MAP_FAILED){
- perror("gc_job_manager_impl::setup_logfiles: mmap");
- close(fd);
- return;
- }
- close(fd);
- memset(p, 0, s);
- d_spu_args[i].log.base = ptr_to_ea(p);
- d_spu_args[i].log.nentries = nentries;
- }
-}
-
-void
-gc_job_manager_impl::sync_logfiles()
-{
- for (unsigned int i = 0; i < d_options.nspes; i++){
- if (d_spu_args[i].log.base)
- msync(ea_to_ptr(d_spu_args[i].log.base),
- d_spu_args[i].log.nentries * sizeof(gc_log_entry_t),
- MS_ASYNC);
- }
-}
-
-void
-gc_job_manager_impl::unmap_logfiles()
-{
- for (unsigned int i = 0; i < d_options.nspes; i++){
- if (d_spu_args[i].log.base)
- munmap(ea_to_ptr(d_spu_args[i].log.base),
- d_spu_args[i].log.nentries * sizeof(gc_log_entry_t));
- }
-}
-
-////////////////////////////////////////////////////////////////////////
-//
-// lookup proc names in d_proc_def table
-
-gc_proc_id_t
-gc_job_manager_impl::lookup_proc(const std::string &proc_name)
-{
- for (int i = 0; i < d_nproc_defs; i++)
- if (proc_name == d_proc_def[i].name)
- return i;
-
- throw gc_unknown_proc(proc_name);
-}
-
-std::vector<std::string>
-gc_job_manager_impl::proc_names()
-{
- std::vector<std::string> r;
- for (int i = 0; i < d_nproc_defs; i++)
- r.push_back(d_proc_def[i].name);
-
- return r;
-}
-
-////////////////////////////////////////////////////////////////////////
-
-worker_ctx::~worker_ctx()
-{
- if (spe_ctx){
- int r = spe_context_destroy(spe_ctx);
- if (r != 0){
- perror("spe_context_destroy");
- }
- spe_ctx = 0;
- }
- state = WS_FREE;
-}
diff --git a/gcell/lib/runtime/gc_job_manager_impl.h b/gcell/lib/runtime/gc_job_manager_impl.h
deleted file mode 100644
index 640fdfe79..000000000
--- a/gcell/lib/runtime/gc_job_manager_impl.h
+++ /dev/null
@@ -1,274 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007,2008,2009,2010 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef INCLUDED_GC_JOB_MANAGER_IMPL_H
-#define INCLUDED_GC_JOB_MANAGER_IMPL_H
-
-#include <gcell/gc_job_manager.h>
-#include <gcell/gc_jd_stack.h>
-#include <gcell/gc_jd_queue.h>
-#include <gcell/gc_spu_args.h>
-#include "gc_client_thread_info.h"
-#include <libspe2.h>
-#include <vector>
-#include <boost/scoped_array.hpp>
-
-typedef boost::shared_ptr<spe_gang_context> spe_gang_context_sptr;
-typedef boost::shared_ptr<spe_program_handle_t> spe_program_handle_sptr;
-typedef boost::scoped_array<gc_client_thread_info> gc_client_thread_info_sa;
-
-
-enum worker_state {
- WS_FREE, // not in use
- WS_INIT, // allocated and being initialized
- WS_RUNNING, // the thread is running
- WS_DEAD, // the thread is dead
-};
-
-struct worker_ctx {
- volatile worker_state state;
- unsigned int spe_idx; // [0, nspes-1]
- spe_context_ptr_t spe_ctx;
- spe_spu_control_area_t *spe_ctrl;
- pthread_t thread;
- gc_spu_args_t *spu_args; // pointer to 16-byte aligned struct
-
- worker_ctx()
- : state(WS_FREE), spe_idx(0), spe_ctx(0), spe_ctrl(0),
- thread(0), spu_args(0) {}
- ~worker_ctx();
-};
-
-enum evt_handler_state {
- EHS_INIT, // being initialized
- EHS_RUNNING, // thread is running
- EHS_SHUTTING_DOWN, // in process of shutting down everything
- EHS_WAITING_FOR_WORKERS_TO_DIE,
- EHS_DEAD, // thread is dead
-};
-
-enum job_completer_state {
- JCS_INIT, // being initialized
- JCS_RUNNING, // thread is running
- JCS_DEAD, // thread is dead
-};
-
-struct spe_event_handler {
- spe_event_handler_ptr_t ptr;
-
- spe_event_handler() : ptr(0) {}
- ~spe_event_handler(){
- if (ptr){
- if (spe_event_handler_destroy(ptr) != 0){
- perror("spe_event_handler_destroy");
- }
- }
- }
-};
-
-
-/*!
- * \brief Concrete class that manages SPE jobs.
- *
- * This class contains all the implementation details.
- */
-class gc_job_manager_impl : public gc_job_manager
-{
- enum { MAX_SPES = 16 };
-
- int d_debug;
- gc_jm_options d_options;
- spe_program_handle_sptr d_spe_image;
- spe_gang_context_sptr d_gang; // boost::shared_ptr
-
- worker_ctx d_worker[MAX_SPES]; // SPE ctx, thread, etc
- gc_spu_args_t *d_spu_args; // 16-byte aligned structs
- boost::shared_ptr<void> _d_spu_args_boost; // hack for automatic storage mgmt
-
- gc_comp_info_t *d_comp_info; // 128-byte aligned structs
- boost::shared_ptr<void> _d_comp_info_boost; // hack for automatic storage mgmt
-
- // used to coordinate communication w/ the event handling thread
- boost::mutex d_eh_mutex;
- boost::condition_variable d_eh_cond;
- pthread_t d_eh_thread; // the event handler thread
- volatile evt_handler_state d_eh_state;
- volatile bool d_shutdown_requested;
- spe_event_handler d_spe_event_handler;
-
- // used to coordinate communication w/ the job completer thread
- boost::mutex d_jc_mutex;
- boost::condition_variable d_jc_cond;
- pthread_t d_jc_thread; // the job completion thread
- volatile job_completer_state d_jc_state;
- int d_jc_njobs_active; // # of jobs submitted but not yet reaped
-
- // round robin notification of spes
- int d_ntell; // # of spes to tell
- unsigned int d_tell_start; // which one to start with
-
- // All of the job descriptors are hung off of here.
- // We allocate them all in a single cache aligned chunk.
- gc_job_desc_t *d_jd; // [options.max_jobs]
- boost::shared_ptr<void> _d_jd_boost; // hack for automatic storage mgmt
-
- gc_client_thread_info_sa d_client_thread; // [options.max_client_threads]
-
- // We use bitvectors to represent the completing state of a job. Each
- // bitvector is d_bvlen longs in length.
- int d_bvlen; // bit vector length in longs
-
- // This contains the storage for all the bitvectors used by the job
- // manager. There's 1 for each client thread, in the d_jobs_done
- // field. We allocate them all in a single cache aligned chunk.
- boost::shared_ptr<void> _d_all_bitvectors; // hack for automatic storage mgmt
-
- // Lock free stack where we keep track of the free job descriptors.
- gc_jd_stack_t *d_free_list; // stack of free job descriptors
- boost::shared_ptr<void> _d_free_list_boost; // hack for automatic storage mgmt
-
- // The PPE inserts jobs here; SPEs pull jobs from here.
- gc_jd_queue_t *d_queue; // job queue
- boost::shared_ptr<void> _d_queue_boost; // hack for automatic storage mgmt
-
- int d_ea_args_maxsize;
-
- struct gc_proc_def *d_proc_def; // the SPE procedure table
- uint32_t d_proc_def_ls_addr; // the LS address of the table
- int d_nproc_defs; // number of proc_defs in table
-
- gc_client_thread_info *alloc_cti();
- void free_cti(gc_client_thread_info *cti);
-
- void create_event_handler();
- void set_eh_state(evt_handler_state s);
- void set_ea_args_maxsize(int maxsize);
-
- void notify_clients_jobs_are_done(unsigned int spe_num,
- unsigned int completion_info_idx);
-
-public:
- void event_handler_loop(); // really private
- void job_completer_loop(); // really private
-
-private:
- bool send_all_spes(uint32_t msg);
- bool send_spe(unsigned int spe, uint32_t msg);
- void print_event(spe_event_unit_t *evt);
- void handle_event(spe_event_unit_t *evt);
- bool incr_njobs_active();
- void decr_njobs_active(int n);
- void tell_spes_to_check_queue();
- void poll_for_job_completion();
-
- // bitvector ops
- void bv_zero(unsigned long *bv);
- void bv_clr(unsigned long *bv, unsigned int bitno);
- void bv_set(unsigned long *bv, unsigned int bitno);
- bool bv_isset(unsigned long *bv, unsigned int bitno);
- bool bv_isclr(unsigned long *bv, unsigned int bitno);
-
- void setup_logfiles();
- void sync_logfiles();
- void unmap_logfiles();
-
- friend gc_job_manager_sptr gc_make_job_manager(const gc_jm_options *options);
-
- gc_job_manager_impl(const gc_jm_options *options = 0);
-
-public:
- virtual ~gc_job_manager_impl();
-
- /*!
- * Stop accepting new jobs. Wait for existing jobs to complete.
- * Return all managed SPE's to the system.
- */
- virtual bool shutdown();
-
- /*!
- * \brief Return number of SPE's currently allocated to job manager.
- */
- virtual int nspes() const;
-
- /*!
- * \brief Return a pointer to a properly aligned job descriptor,
- * or zero if none are available.
- */
- virtual gc_job_desc *alloc_job_desc();
-
- /*
- *! Return a job descriptor previously allocated with alloc_job_desc()
- *
- * \param[in] jd pointer to job descriptor to free.
- */
- virtual void free_job_desc(gc_job_desc *jd);
-
- /*!
- * \brief Submit a job for asynchronous processing on an SPE.
- *
- * \param[in] jd pointer to job description
- *
- * The caller must not read or write the job description
- * or any of the memory associated with any indirect arguments
- * until after calling wait_job.
- *
- * \returns true iff the job was successfully enqueued.
- * If submit_job returns false, check jd->status for additional info.
- */
- virtual bool submit_job(gc_job_desc *jd);
-
- /*!
- * \brief Wait for job to complete.
- *
- * A thread may only wait for jobs which it submitted.
- *
- * \returns true if sucessful, else false.
- */
- virtual bool
- wait_job(gc_job_desc *jd);
-
- /*!
- * \brief wait for 1 or more jobs to complete.
- *
- * \param[in] njobs is the length of arrays \p jd and \p done.
- * \param[in] jd are the jobs that are to be waited for.
- * \param[out] done indicates whether the corresponding job is complete.
- * \param[in] mode indicates whether to wait for ALL or ANY of the jobs
- * in \p jd to complete.
- *
- * A thread may only wait for jobs which it submitted.
- *
- * \returns number of jobs completed, or -1 if error.
- */
- virtual int
- wait_jobs(unsigned int njobs,
- gc_job_desc *jd[], bool done[], gc_wait_mode mode);
-
- virtual int ea_args_maxsize();
-
- virtual gc_proc_id_t lookup_proc(const std::string &name);
- virtual std::vector<std::string> proc_names();
-
- virtual void set_debug(int debug);
- virtual int debug();
-};
-
-#endif /* INCLUDED_GC_JOB_MANAGER_IMPL_H */
diff --git a/gcell/lib/runtime/gc_proc_def_utils.cc b/gcell/lib/runtime/gc_proc_def_utils.cc
deleted file mode 100644
index 0250d677a..000000000
--- a/gcell/lib/runtime/gc_proc_def_utils.cc
+++ /dev/null
@@ -1,123 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2008 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <gc_proc_def_utils.h>
-#include <gcell/gc_declare_proc.h>
-#include <elf.h>
-#include <stdio.h>
-#include <string.h>
-
-static const unsigned char expected[EI_PAD] = {
- ELFMAG0,
- ELFMAG1,
- ELFMAG2,
- ELFMAG3,
- ELFCLASS32,
- ELFDATA2MSB,
- EV_CURRENT,
- ELFOSABI_SYSV,
- 0
-};
-
-
-/*
- * Basically we're going to find the GC_PROC_DEF_SECTION section
- * in the ELF file and return a pointer to it. The only things in that
- * section are gc_proc_def's
- */
-bool
-gcpd_find_table(spe_program_handle_t *handle,
- struct gc_proc_def **table, int *nentries, uint32_t *ls_addr)
-{
- if (!handle || !table || !nentries)
- return false;
-
- *table = 0;
- *nentries = 0;
-
- Elf32_Ehdr *ehdr = (Elf32_Ehdr *)handle->elf_image;
- if (!ehdr){
- fprintf(stderr, "gcpd: No ELF image has been loaded\n");
- return false;
- }
-
- // quick check that we're looking at a SPE EXEC object
-
- if (memcmp(ehdr->e_ident, expected, EI_PAD) != 0){
- fprintf(stderr, "gcpd: invalid ELF header\n");
- return false;
- }
-
- if (ehdr->e_machine != 0x17){ // confirm machine type (EM_SPU)
- fprintf(stderr, "gcpd: not an SPE ELF object\n");
- return false;
- }
-
- if (ehdr->e_type != ET_EXEC){
- fprintf(stderr, "gcpd: invalid SPE ELF type.\n");
- fprintf(stderr, "gcpd: SPE type %d != %d\n", ehdr->e_type, ET_EXEC);
- return false;
- }
-
- // find the section header table
-
- Elf32_Shdr *shdr;
- Elf32_Shdr *sh;
-
- if (ehdr->e_shentsize != sizeof (*shdr)){
- fprintf(stderr, "gcpd: invalid section header format.\n");
- return false;
- }
-
- if (ehdr->e_shnum == 0){
- fprintf(stderr, "gcpd: no section headers in file.\n");
- return false;
- }
-
- shdr = (Elf32_Shdr *) ((char *)ehdr + ehdr->e_shoff);
- char *str_table = (char *)ehdr + shdr[ehdr->e_shstrndx].sh_offset;
-
- // traverse the sections looking for GC_PROC_DEF_SECTION
-
- for (sh = shdr; sh < &shdr[ehdr->e_shnum]; sh++){
- if (0){
- fprintf(stderr, "section name: %s (start: 0x%04x, size: 0x%04x)\n",
- str_table + sh->sh_name, sh->sh_offset, sh->sh_size);
- }
-
- if (strcmp(GC_PROC_DEF_SECTION, str_table+sh->sh_name) == 0){
- *table = (struct gc_proc_def *)((char *)ehdr + sh->sh_offset);
- if (sh->sh_size % (sizeof(struct gc_proc_def)) != 0){
- fprintf(stderr, "gcpd: %s section has invalid format\n", GC_PROC_DEF_SECTION);
- return false;
- }
- *nentries = sh->sh_size / sizeof(struct gc_proc_def);
- *ls_addr = sh->sh_addr;
- return true;
- }
- }
-
- return false;
-}
diff --git a/gcell/lib/runtime/gc_proc_def_utils.h b/gcell/lib/runtime/gc_proc_def_utils.h
deleted file mode 100644
index 79c9b51aa..000000000
--- a/gcell/lib/runtime/gc_proc_def_utils.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2008 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef INCLUDED_GC_PROC_DEF_UTILS_H
-#define INCLUDED_GC_PROC_DEF_UTILS_H
-
-#include <gcell/gc_declare_proc.h>
-#include <libspe2.h>
-
-/*!
- * \brief find the gc_proc_def table in the SPE program
- *
- * \param[in] program is the handle to the loaded SPE program
- * \param[out] table points to the table, if it's found
- * \param[out] nentries is set to the number of entries in the table.
- * \param[out] ls_addr is set to the Local Store address of the table
- *
- * \returns true if successful, else false
- */
-bool
-gcpd_find_table(spe_program_handle_t *program,
- struct gc_proc_def **table, int *nentries, uint32_t *ls_addr);
-
-
-#endif /* INCLUDED_GC_PROC_DEF_UTILS_H */
diff --git a/gcell/lib/runtime/gcell-embedspu-libtool b/gcell/lib/runtime/gcell-embedspu-libtool
deleted file mode 100755
index c206086a4..000000000
--- a/gcell/lib/runtime/gcell-embedspu-libtool
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/bin/bash
-#
-# Take a spu executable and turn into into a libtool compatible .lo (and .o) file.
-# This is needed when you want to embed a SPU executable into a shared library.
-#
-# The symbol assigned to the embedded executable is the basename of the
-# output file with an _spx appended. E.g., if the output filename is
-# my_spe_tricks.lo the symbol name is my_spe_tricks_spx.
-# ("_spx" stands for SPE executable)
-
-if [ $# -ne 2 ]; then
- echo "usage: gcell-embedspu-libtool spu_executable output_file.lo " 1>&2
- exit 1
-fi
-
-spu_executable=$1
-lo_file=$2
-symbol_name=${lo_file%%.lo}_spx
-
-# try to make .libs in case it's not there
-mkdir .libs >/dev/null 2>/dev/null
-
-# generate the .o file that wraps the SPU executable
-ppu-embedspu -m32 -fpic ${symbol_name} ${spu_executable} .libs/${symbol_name}.o
-
-# generate the .lo libtool file that points at all the right places
-rm -f $lo_file
-cat >$lo_file.new <<EOF
-# $lo_file - a libtool object file
-# Generated by ltmain.sh - GNU libtool 1.5.22 (1.1220.2.365 2005/12/18 22:14:06)
-#
-# Please DO NOT delete this file!
-# It is necessary for linking the library.
-
-pic_object='.libs/${symbol_name}.o'
-non_pic_object=none
-EOF
-
-mv $lo_file.new $lo_file
-
diff --git a/gcell/lib/runtime/qa_gcell_runtime.cc b/gcell/lib/runtime/qa_gcell_runtime.cc
deleted file mode 100644
index fef9a7fb4..000000000
--- a/gcell/lib/runtime/qa_gcell_runtime.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-/*
- * This class gathers together all the test cases for the lib
- * directory into a single test suite. As you create new test cases,
- * add them here.
- */
-
-#include <qa_gcell_runtime.h>
-#include <qa_jd_stack.h>
-#include <qa_jd_queue.h>
-#include <qa_job_manager.h>
-
-CppUnit::TestSuite *
-qa_gcell_runtime::suite()
-{
- CppUnit::TestSuite *s = new CppUnit::TestSuite("runtime");
-
- s->addTest(qa_jd_stack::suite());
- s->addTest(qa_jd_queue::suite());
- s->addTest(qa_job_manager::suite());
-
- return s;
-}
diff --git a/gcell/lib/runtime/qa_gcell_runtime.h b/gcell/lib/runtime/qa_gcell_runtime.h
deleted file mode 100644
index 36180c919..000000000
--- a/gcell/lib/runtime/qa_gcell_runtime.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef INCLUDED_QA_GCELL_RUNTIME_H
-#define INCLUDED_QA_GCELL_RUNTIME_H
-
-#include <cppunit/TestSuite.h>
-
-//! collect all the tests for the runtime directory
-
-class qa_gcell_runtime {
-public:
- //! return suite of tests
- static CppUnit::TestSuite *suite();
-};
-
-
-#endif /* INCLUDED_QA_GCELL_RUNTIME_H */
diff --git a/gcell/lib/runtime/qa_jd_queue.cc b/gcell/lib/runtime/qa_jd_queue.cc
deleted file mode 100644
index 35ab9d82f..000000000
--- a/gcell/lib/runtime/qa_jd_queue.cc
+++ /dev/null
@@ -1,78 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "qa_jd_queue.h"
-#include <cppunit/TestAssert.h>
-#include <gcell/gc_jd_queue.h>
-#include <stdio.h>
-
-
-
-static const int NJDS = 16;
-static gc_jd_queue_t queue;
-static gc_job_desc_t jds[NJDS];
-
-// no brainer, single threaded basic checkout
-void
-qa_jd_queue::t1()
-{
- // N.B., queue allocated stuff doesn't obey ((aligned (N))) attributes
- //const int NJDS = 8;
- //gc_jd_queue_t queue;
- //gc_job_desc_t jds[NJDS];
-
- //printf("&queue = %p\n", &queue);
- //printf("&jds[0] = %p\n", &jds[0]);
- //printf("&jds[1] = %p\n", &jds[1]);
-
- CPPUNIT_ASSERT(((uintptr_t) &queue & 0x7f) == 0);
- CPPUNIT_ASSERT(((uintptr_t) &jds[0] & 0x7f) == 0);
- CPPUNIT_ASSERT(((uintptr_t) &jds[1] & 0x7f) == 0);
-
- gc_jd_queue_init(&queue);
-
- CPPUNIT_ASSERT(gc_jd_queue_dequeue(&queue) == 0);
-
- gc_jd_queue_enqueue(&queue, &jds[0]);
- CPPUNIT_ASSERT_EQUAL(&jds[0], gc_jd_queue_dequeue(&queue));
-
- CPPUNIT_ASSERT(gc_jd_queue_dequeue(&queue) == 0);
-
- for (int i = 0; i < NJDS; i++)
- gc_jd_queue_enqueue(&queue, &jds[i]);
-
- for (int i = 0; i < NJDS; i++)
- CPPUNIT_ASSERT_EQUAL(&jds[i], gc_jd_queue_dequeue(&queue));
-
- CPPUNIT_ASSERT(gc_jd_queue_dequeue(&queue) == 0);
-}
-
-// FIXME multithreaded (running on PPE)
-void
-qa_jd_queue::t2()
-{
-}
-
-// FIXME multithreaded (running on PPE & SPE)
-void
-qa_jd_queue::t3()
-{
-}
diff --git a/gcell/lib/runtime/qa_jd_queue.h b/gcell/lib/runtime/qa_jd_queue.h
deleted file mode 100644
index 5e1aab84f..000000000
--- a/gcell/lib/runtime/qa_jd_queue.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef INCLUDED_QA_JD_QUEUE_H
-#define INCLUDED_QA_JD_QUEUE_H
-
-#include <cppunit/extensions/HelperMacros.h>
-#include <cppunit/TestCase.h>
-
-class qa_jd_queue : public CppUnit::TestCase {
-
- CPPUNIT_TEST_SUITE(qa_jd_queue);
- CPPUNIT_TEST(t1);
- CPPUNIT_TEST(t2);
- CPPUNIT_TEST(t3);
- CPPUNIT_TEST_SUITE_END();
-
- private:
- void t1();
- void t2();
- void t3();
-};
-
-
-#endif /* INCLUDED_QA_JD_QUEUE_H */
diff --git a/gcell/lib/runtime/qa_jd_stack.cc b/gcell/lib/runtime/qa_jd_stack.cc
deleted file mode 100644
index ce4ce2d0d..000000000
--- a/gcell/lib/runtime/qa_jd_stack.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "qa_jd_stack.h"
-#include <cppunit/TestAssert.h>
-#include <gcell/gc_jd_stack.h>
-#include <stdio.h>
-
-
-
-static const int NJDS = 8;
-static gc_jd_stack_t stack;
-static gc_job_desc_t jds[NJDS];
-
-// no brainer, single threaded basic checkout
-void
-qa_jd_stack::t1()
-{
- // N.B., stack allocated stuff doesn't obey ((aligned (N))) attributes
- //const int NJDS = 8;
- //gc_jd_stack_t stack;
- //gc_job_desc_t jds[NJDS];
-
- //printf("&stack = %p\n", &stack);
- //printf("&jds[0] = %p\n", &jds[0]);
- //printf("&jds[1] = %p\n", &jds[1]);
-
- CPPUNIT_ASSERT(((uintptr_t) &stack & 0x7f) == 0);
- CPPUNIT_ASSERT(((uintptr_t) &jds[0] & 0x7f) == 0);
- CPPUNIT_ASSERT(((uintptr_t) &jds[1] & 0x7f) == 0);
-
- gc_jd_stack_init(&stack);
-
- CPPUNIT_ASSERT(gc_jd_stack_pop(&stack) == 0);
-
- for (int i = 0; i < NJDS; i++)
- gc_jd_stack_push(&stack, &jds[i]);
-
- for (int i = 0; i < NJDS; i++)
- CPPUNIT_ASSERT_EQUAL(&jds[NJDS - i - 1], gc_jd_stack_pop(&stack));
-
- CPPUNIT_ASSERT(gc_jd_stack_pop(&stack) == 0);
-}
-
-// FIXME multithreaded (running on PPE)
-void
-qa_jd_stack::t2()
-{
-}
diff --git a/gcell/lib/runtime/qa_jd_stack.h b/gcell/lib/runtime/qa_jd_stack.h
deleted file mode 100644
index 1546bbf9f..000000000
--- a/gcell/lib/runtime/qa_jd_stack.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef INCLUDED_QA_JD_STACK_H
-#define INCLUDED_QA_JD_STACK_H
-
-#include <cppunit/extensions/HelperMacros.h>
-#include <cppunit/TestCase.h>
-
-class qa_jd_stack : public CppUnit::TestCase {
-
- CPPUNIT_TEST_SUITE(qa_jd_stack);
- CPPUNIT_TEST(t1);
- CPPUNIT_TEST(t2);
- CPPUNIT_TEST_SUITE_END();
-
- private:
- void t1();
- void t2();
-
-};
-
-
-
-#endif /* INCLUDED_QA_JD_STACK_H */
diff --git a/gcell/lib/runtime/qa_job_manager.cc b/gcell/lib/runtime/qa_job_manager.cc
deleted file mode 100644
index 45cf26cfc..000000000
--- a/gcell/lib/runtime/qa_job_manager.cc
+++ /dev/null
@@ -1,790 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007,2008 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "qa_job_manager.h"
-#include <cppunit/TestAssert.h>
-#include <gcell/gc_job_manager.h>
-#include <stdexcept>
-#include <stdio.h>
-#include <time.h>
-#include <errno.h>
-#include <string.h>
-
-#include <malloc.h>
-
-// handle to embedded SPU executable w/ QA routines
-extern spe_program_handle_t gcell_runtime_qa_spx;
-
-#if 0
-static void
-gc_msleep(unsigned long millisecs)
-{
- int r;
- struct timespec tv;
- tv.tv_sec = millisecs / 1000;
- tv.tv_nsec = (millisecs - (tv.tv_sec * 1000)) * 1000000;
-
- while (1){
- r = nanosleep(&tv, &tv);
- if (r == 0)
- return;
- if (r == -1 && errno == EINTR)
- continue;
- perror("nanosleep");
- return;
- }
-}
-#endif
-
-void
-qa_job_manager::leak_check(test_t t, const std::string &name)
-{
- struct mallinfo before, after;
-
- before = mallinfo();
- (this->*t)();
- after = mallinfo();
-
- size_t delta = after.uordblks - before.uordblks;
- if (delta != 0){
- std::cout << name << " leaked memory\n";
- printf(" before.uordblks = %6d\n", before.uordblks);
- printf(" after.uordblks = %6d\n", after.uordblks);
- printf(" delta = %d\n", after.uordblks - before.uordblks);
- }
-}
-
-void
-qa_job_manager::t0()
-{
- //leak_check(&qa_job_manager::t1_body, "t1-0");
-}
-
-void
-qa_job_manager::t1()
-{
- t1_body(); // leaks 800 bytes first time, could be one-time inits
- leak_check(&qa_job_manager::t1_body, "t1");
-}
-
-void
-qa_job_manager::t2()
-{
- leak_check(&qa_job_manager::t2_body, "t2");
-}
-
-void
-qa_job_manager::t3()
-{
- t3_body(); // leaks first time only, could be cppunit
- leak_check(&qa_job_manager::t3_body, "t3");
-}
-
-void
-qa_job_manager::t4()
-{
- leak_check(&qa_job_manager::t4_body, "t4");
-}
-
-void
-qa_job_manager::t5()
-{
- leak_check(&qa_job_manager::t5_body, "t5");
-}
-
-void
-qa_job_manager::t6()
-{
- leak_check(&qa_job_manager::t6_body, "t6");
-}
-
-void
-qa_job_manager::t7()
-{
- leak_check(&qa_job_manager::t7_body, "t7");
-}
-
-void
-qa_job_manager::t8()
-{
- leak_check(&qa_job_manager::t8_body, "t8");
-}
-
-void
-qa_job_manager::t9()
-{
- leak_check(&qa_job_manager::t9_body, "t9");
-}
-
-void
-qa_job_manager::t10()
-{
- leak_check(&qa_job_manager::t10_body, "t10");
-}
-
-void
-qa_job_manager::t11()
-{
- leak_check(&qa_job_manager::t11_body, "t11");
-}
-
-void
-qa_job_manager::t12()
-{
- leak_check(&qa_job_manager::t12_body, "t12");
-}
-
-void
-qa_job_manager::t13()
-{
- leak_check(&qa_job_manager::t13_body, "t13");
-}
-
-void
-qa_job_manager::t14()
-{
- leak_check(&qa_job_manager::t14_body, "t14");
-}
-
-void
-qa_job_manager::t15()
-{
- leak_check(&qa_job_manager::t15_body, "t15");
-}
-
-// ----------------------------------------------------------------
-
-void
-qa_job_manager::t1_body()
-{
- gc_job_manager_sptr mgr;
- gc_jm_options opts;
- opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa_spx);
- mgr = gc_make_job_manager(&opts);
-}
-
-void
-qa_job_manager::t2_body()
-{
- gc_job_manager_sptr mgr;
- gc_jm_options opts;
- opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa_spx);
- opts.nspes = 100;
- opts.gang_schedule = false;
- mgr = gc_make_job_manager(&opts);
-}
-
-void
-qa_job_manager::t3_body()
-{
- // This leaks memory the first time it's invoked, but I'm not sure
- // if it's us or the underlying exception handling mechanism, or
- // cppunit. cppunit is the prime suspect.
-
-#if 0
- gc_job_manager_sptr mgr;
- gc_jm_options opts;
- opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa_spx);
- opts.nspes = 100;
- opts.gang_schedule = true;
- CPPUNIT_ASSERT_THROW(mgr = gc_make_job_manager(&opts), std::out_of_range);
-#endif
-}
-
-static void
-init_jd(gc_job_desc *jd, gc_proc_id_t proc_id)
-{
- jd->proc_id = proc_id;
- jd->input.nargs = 0;
- jd->output.nargs = 0;
- jd->eaa.nargs = 0;
-}
-
-void
-qa_job_manager::t4_body()
-{
- gc_job_manager_sptr mgr;
- gc_jm_options opts;
- opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa_spx);
- opts.nspes = 1;
- mgr = gc_make_job_manager(&opts);
- //mgr->set_debug(-1);
- static const int NJOBS = 32;
- gc_job_desc *jds[NJOBS];
- bool done[NJOBS];
-
- gc_proc_id_t gcp_no_such;
- CPPUNIT_ASSERT_THROW(gcp_no_such = mgr->lookup_proc("--no-such-proc-name--"), gc_unknown_proc);
-
- gc_proc_id_t gcp_qa_nop = mgr->lookup_proc("qa_nop");
- CPPUNIT_ASSERT(gcp_qa_nop != GCP_UNKNOWN_PROC);
-
- for (int i = 0; i < NJOBS; i++){
- jds[i] = mgr->alloc_job_desc();
- init_jd(jds[i], gcp_qa_nop);
- }
-
- for (int i = 0; i < NJOBS; i++){
- if (!mgr->submit_job(jds[i])){
- printf("%d: submit_job(jds[%d]) failed, status = %d\n",
- __LINE__, i, jds[i]->status);
- }
- }
-
- int n = mgr->wait_jobs(NJOBS, jds, done, GC_WAIT_ALL);
- CPPUNIT_ASSERT_EQUAL(NJOBS, n);
-
- for (int i = 0; i < NJOBS; i++){
- mgr->free_job_desc(jds[i]);
- }
-}
-
-void
-qa_job_manager::t5_body()
-{
- gc_job_manager_sptr mgr;
- gc_jm_options opts;
- opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa_spx);
- opts.nspes = 0; // use them all
- mgr = gc_make_job_manager(&opts);
- //mgr->set_debug(-1);
- static const int NJOBS = 32;
- gc_job_desc *jds[NJOBS];
- bool done[NJOBS];
-
- gc_proc_id_t gcp_qa_nop = mgr->lookup_proc("qa_nop");
-
- for (int i = 0; i < NJOBS; i++){
- jds[i] = mgr->alloc_job_desc();
- init_jd(jds[i], gcp_qa_nop);
- }
-
- for (int i = 0; i < NJOBS; i++){
- if (!mgr->submit_job(jds[i])){
- printf("%d: submit_job(jds[%d]) failed, status = %d\n",
- __LINE__, i, jds[i]->status);
- }
- }
-
- int n = mgr->wait_jobs(NJOBS, jds, done, GC_WAIT_ALL);
- CPPUNIT_ASSERT_EQUAL(NJOBS, n);
-
- for (int i = 0; i < NJOBS; i++){
- mgr->free_job_desc(jds[i]);
- }
-}
-
-void
-qa_job_manager::t6_body()
-{
- gc_job_manager_sptr mgr;
- gc_jm_options opts;
- opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa_spx);
- opts.nspes = 1;
- mgr = gc_make_job_manager(&opts);
- gc_proc_id_t gcp_qa_nop = mgr->lookup_proc("qa_nop");
- gc_job_desc *jd = mgr->alloc_job_desc();
-
-
- // test for success with gcp_qa_nop procedure
- init_jd(jd, gcp_qa_nop);
- if (!mgr->submit_job(jd)){
- printf("%d: submit_job(jd) failed, status = %d\n", __LINE__, jd->status);
- }
- else {
- mgr->wait_job(jd);
- CPPUNIT_ASSERT_EQUAL(JS_OK, jd->status);
- }
-
- // test for JS_UNKNOWN_PROC with bogus procedure
- init_jd(jd, -2);
- if (!mgr->submit_job(jd)){
- printf("%d: submit_job(jd) failed, status = %d\n", __LINE__, jd->status);
- }
- else {
- mgr->wait_job(jd);
- CPPUNIT_ASSERT_EQUAL(JS_UNKNOWN_PROC, jd->status);
- }
-
- mgr->free_job_desc(jd);
-}
-
-static int
-sum_shorts(short *p, int nshorts)
-{
- int total = 0;
- for (int i = 0; i < nshorts; i++)
- total += p[i];
-
- return total;
-}
-
-static void
-test_sum_shorts(gc_job_manager_sptr mgr, short *buf, int nshorts)
-{
- gc_job_desc *jd = mgr->alloc_job_desc();
- gc_proc_id_t gcp_qa_sum_shorts = mgr->lookup_proc("qa_sum_shorts");
-
- init_jd(jd, gcp_qa_sum_shorts);
- jd->eaa.nargs = 1;
- jd->eaa.arg[0].ea_addr = ptr_to_ea(buf);
- jd->eaa.arg[0].direction = GCJD_DMA_GET;
- jd->eaa.arg[0].get_size = nshorts * sizeof(short);
-
-
- if (!mgr->submit_job(jd)){
- printf("%d: submit_job(jd) failed, status = %d\n", __LINE__, jd->status);
- }
- else {
- mgr->wait_job(jd);
- CPPUNIT_ASSERT_EQUAL(JS_OK, jd->status);
- int expected = sum_shorts(buf, nshorts);
- int actual = jd->output.arg[0].s32;
- CPPUNIT_ASSERT_EQUAL(expected, actual);
- }
-
- mgr->free_job_desc(jd);
-}
-
-static const int NS = 32768;
-static short short_buf[NS] _AL128; // for known alignment
-
-//
-// test all "get" alignments and sizes
-//
-void
-qa_job_manager::t7_body()
-{
- gc_job_manager_sptr mgr;
- gc_jm_options opts;
- opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa_spx);
- opts.nspes = 1;
- mgr = gc_make_job_manager(&opts);
-
- int ea_args_maxsize = mgr->ea_args_maxsize();
-
- for (int i = 0; i < NS; i++) // init buffer with known qty
- short_buf[i] = 0x1234 + i;
-
- for (int offset = 0; offset <= 128; offset++){
- for (int len = 0; len <= 128; len++){
- test_sum_shorts(mgr, &short_buf[offset], len);
- }
- }
-
- // confirm maximum length
- for (int offset = 0; offset <= 64; offset++){
- test_sum_shorts(mgr, &short_buf[offset], ea_args_maxsize/sizeof(short));
- }
-}
-
-//
-// test "get" args too long
-//
-void
-qa_job_manager::t8_body()
-{
- gc_job_manager_sptr mgr;
- gc_jm_options opts;
- opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa_spx);
- opts.nspes = 1;
- mgr = gc_make_job_manager(&opts);
- gc_job_desc *jd = mgr->alloc_job_desc();
- gc_proc_id_t gcp_qa_sum_shorts = mgr->lookup_proc("qa_sum_shorts");
-
- init_jd(jd, gcp_qa_sum_shorts);
- jd->eaa.nargs = 1;
- jd->eaa.arg[0].ea_addr = 0;
- jd->eaa.arg[0].direction = GCJD_DMA_GET;
- jd->eaa.arg[0].get_size = 1 << 20;
-
- if (!mgr->submit_job(jd)){
- printf("%d: submit_job(jd) failed, status = %d\n", __LINE__, jd->status);
- }
- else {
- mgr->wait_job(jd);
- CPPUNIT_ASSERT_EQUAL(JS_ARGS_TOO_LONG, jd->status);
- }
-
- mgr->free_job_desc(jd);
-}
-
-//
-// test MAX_ARGS_EA "get" case
-//
-void
-qa_job_manager::t9_body()
-{
- static const int N = 127;
- static const int M = 201;
- gc_job_manager_sptr mgr;
- gc_jm_options opts;
- opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa_spx);
- opts.nspes = 1;
- mgr = gc_make_job_manager(&opts);
- gc_job_desc *jd = mgr->alloc_job_desc();
- gc_proc_id_t gcp_qa_sum_shorts = mgr->lookup_proc("qa_sum_shorts");
-
- init_jd(jd, gcp_qa_sum_shorts);
- jd->eaa.nargs = MAX_ARGS_EA;
- for (int i = 0; i < MAX_ARGS_EA; i++){
- jd->eaa.arg[i].direction = GCJD_DMA_GET;
- jd->eaa.arg[i].ea_addr = ptr_to_ea(&short_buf[i * M]);
- jd->eaa.arg[i].get_size = N * sizeof(short);
- }
-
- if (!mgr->submit_job(jd)){
- printf("%d: submit_job(jd) failed, status = %d\n", __LINE__, jd->status);
- }
- else {
- mgr->wait_job(jd);
- CPPUNIT_ASSERT_EQUAL(JS_OK, jd->status);
- for (int i = 0; i < MAX_ARGS_EA; i++){
- int expected = sum_shorts(&short_buf[i * M], N);
- int actual = jd->output.arg[i].s32;
- CPPUNIT_ASSERT_EQUAL(expected, actual);
- }
- }
-
- mgr->free_job_desc(jd);
-}
-
-static bool
-confirm_const(const unsigned char *buf, size_t len, unsigned char v)
-{
- bool ok = true;
-
- for (size_t i = 0; i < len; i++){
- if (buf[i] != v){
- ok = false;
- printf("confirm_const: buf[%6d] = 0x%02x, expected = 0x%02x\n",
- i, buf[i], v);
- }
- }
-
- return ok;
-}
-
-static bool
-confirm_seq(const unsigned char *buf, size_t len, unsigned char v)
-{
- bool ok = true;
-
- for (size_t i = 0; i < len; i++, v++){
- if (buf[i] != v){
- ok = false;
- printf("confirm_seq: buf[%6d] = 0x%02x, expected = 0x%02x\n",
- i, buf[i], v);
- }
- }
-
- return ok;
-}
-
-static void
-test_put_seq(gc_job_manager_sptr mgr, int offset, int len, int starting_val)
-{
- gc_job_desc *jd = mgr->alloc_job_desc();
- gc_proc_id_t gcp_qa_put_seq = mgr->lookup_proc("qa_put_seq");
-
- unsigned char *buf = (unsigned char *) short_buf;
- size_t buf_len = sizeof(short_buf);
- memset(buf, 0xff, buf_len);
-
- // two cache lines into the buffer, so we can check before and after
- int fixed_offset = 256;
-
- init_jd(jd, gcp_qa_put_seq);
- jd->input.nargs = 1;
- jd->input.arg[0].s32 = starting_val;
- jd->eaa.nargs = 1;
- jd->eaa.arg[0].ea_addr = ptr_to_ea(buf + fixed_offset + offset);
- jd->eaa.arg[0].direction = GCJD_DMA_PUT;
- jd->eaa.arg[0].put_size = len;
-
- if (!mgr->submit_job(jd)){
- printf("%d: submit_job(jd) failed, status = %d\n", __LINE__, jd->status);
- }
- else {
- mgr->wait_job(jd);
- CPPUNIT_ASSERT_EQUAL(JS_OK, jd->status);
-
- // check before
- CPPUNIT_ASSERT(confirm_const(&buf[0], fixed_offset + offset, 0xff));
-
- // check sequence
- CPPUNIT_ASSERT(confirm_seq(&buf[fixed_offset + offset], len, starting_val));
-
- // check after
- CPPUNIT_ASSERT(confirm_const(&buf[fixed_offset + offset + len],
- buf_len - fixed_offset - offset - len, 0xff));
- }
- mgr->free_job_desc(jd);
-}
-
-//
-// Test all "put" alignments and sizes
-//
-void
-qa_job_manager::t10_body()
-{
- gc_job_manager_sptr mgr;
- gc_jm_options opts;
- opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa_spx);
- opts.nspes = 1;
- mgr = gc_make_job_manager(&opts);
-
- int starting_val = 13;
-
- for (int offset = 0; offset <= 128; offset++){
- for (int len = 0; len <= 128; len++){
- test_put_seq(mgr, offset, len, starting_val++);
- }
- }
-
- int ea_args_maxsize = mgr->ea_args_maxsize();
-
- // confirm maximum length
- for (int offset = 0; offset <= 64; offset++){
- test_put_seq(mgr, offset, ea_args_maxsize, starting_val++);
- }
-}
-
-//
-// test "put" args too long
-//
-void
-qa_job_manager::t11_body()
-{
- gc_job_manager_sptr mgr;
- gc_jm_options opts;
- opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa_spx);
- opts.nspes = 1;
- mgr = gc_make_job_manager(&opts);
- gc_job_desc *jd = mgr->alloc_job_desc();
- gc_proc_id_t gcp_qa_put_seq = mgr->lookup_proc("qa_put_seq");
-
- init_jd(jd, gcp_qa_put_seq);
- jd->input.nargs = 1;
- jd->input.arg[0].s32 = 0;
- jd->eaa.nargs = 1;
- jd->eaa.arg[0].ea_addr = 0;
- jd->eaa.arg[0].direction = GCJD_DMA_PUT;
- jd->eaa.arg[0].put_size = 1 << 20;
-
- if (!mgr->submit_job(jd)){
- printf("%d: submit_job(jd) failed, status = %d\n", __LINE__, jd->status);
- }
- else {
- mgr->wait_job(jd);
- CPPUNIT_ASSERT_EQUAL(JS_ARGS_TOO_LONG, jd->status);
- }
-
- mgr->free_job_desc(jd);
-}
-
-//
-// test MAX_ARGS_EA "put" case
-//
-void
-qa_job_manager::t12_body()
-{
- static const int N = 127;
- static const int M = 201;
- gc_job_manager_sptr mgr;
- gc_jm_options opts;
- opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa_spx);
- opts.nspes = 1;
- mgr = gc_make_job_manager(&opts);
- gc_job_desc *jd = mgr->alloc_job_desc();
- gc_proc_id_t gcp_qa_put_seq = mgr->lookup_proc("qa_put_seq");
-
- unsigned char *buf = (unsigned char *) short_buf;
- size_t buf_len = sizeof(short_buf);
- memset(buf, 0xff, buf_len);
-
- // two cache lines into the buffer, so we can check before and after
- int fixed_offset = 256;
-
- int starting_val = 13;
-
- init_jd(jd, gcp_qa_put_seq);
- jd->input.nargs = 1;
- jd->input.arg[0].s32 = starting_val;
- jd->eaa.nargs = MAX_ARGS_EA;
- for (int i = 0; i < MAX_ARGS_EA; i++){
- jd->eaa.arg[i].direction = GCJD_DMA_PUT;
- jd->eaa.arg[i].ea_addr = ptr_to_ea(&buf[i * M + fixed_offset]);
- jd->eaa.arg[i].put_size = N;
- }
-
- if (!mgr->submit_job(jd)){
- printf("%d: submit_job(jd) failed, status = %d\n", __LINE__, jd->status);
- }
- else {
- mgr->wait_job(jd);
- CPPUNIT_ASSERT_EQUAL(JS_OK, jd->status);
- for (int i = 0; i < MAX_ARGS_EA; i++){
- CPPUNIT_ASSERT(confirm_seq(&buf[i * M + fixed_offset], N, starting_val));
- starting_val += N;
- }
- }
-
- mgr->free_job_desc(jd);
-}
-
-//
-// test qa_copy primitive
-//
-void
-qa_job_manager::t13_body()
-{
- gc_job_manager_sptr mgr;
- gc_jm_options opts;
- opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa_spx);
- opts.nspes = 1;
- mgr = gc_make_job_manager(&opts);
-
- memset(short_buf, 0, sizeof(short_buf));
- for (int i = 0; i < NS/2; i++) // init buffer with known qty
- short_buf[i] = 0x1234 + i;
-
- int nshorts = NS/2;
-
- gc_job_desc *jd = mgr->alloc_job_desc();
- gc_proc_id_t gcp_qa_copy = mgr->lookup_proc("qa_copy");
-
-#if 0
- printf("gcq_qa_copy = %d\n", gcp_qa_copy);
- std::vector<std::string> procs = mgr->proc_names();
- for (unsigned int i = 0; i < procs.size(); ++i)
- std::cout << procs[i] << std::endl;
-#endif
-
- init_jd(jd, gcp_qa_copy);
- jd->eaa.nargs = 2;
- jd->eaa.arg[0].ea_addr = ptr_to_ea(&short_buf[nshorts]);
- jd->eaa.arg[0].direction = GCJD_DMA_PUT;
- jd->eaa.arg[0].put_size = nshorts * sizeof(short);
-
- jd->eaa.arg[1].ea_addr = ptr_to_ea(&short_buf[0]);
- jd->eaa.arg[1].direction = GCJD_DMA_GET;
- jd->eaa.arg[1].get_size = nshorts * sizeof(short);
-
-
- if (!mgr->submit_job(jd)){
- printf("%d: submit_job(jd) failed, status = %d\n", __LINE__, jd->status);
- }
- else {
- mgr->wait_job(jd);
- CPPUNIT_ASSERT_EQUAL(JS_OK, jd->status);
- CPPUNIT_ASSERT_EQUAL(0, jd->output.arg[0].s32);
-
- bool ok = true;
- for (int i = 0; i < nshorts; i++){
- if (short_buf[i] != short_buf[i + nshorts])
- ok = false;
- }
- CPPUNIT_ASSERT(ok);
- }
- mgr->free_job_desc(jd);
-}
-
-/*
- * Parallel submission of NJOBS "put" jobs will test double buffered puts.
- */
-void
-qa_job_manager::t14_body()
-{
- //return;
-
- //static const int NJOBS = 64;
- static const int NJOBS = 128;
- static const int LEN_PER_JOB = 1021;
- unsigned char buf[NJOBS * LEN_PER_JOB];
- gc_job_desc_t *jd[NJOBS];
- bool done[NJOBS];
-
- static const int STARTING_VAL = 13;
-
- memset(buf, 0xff, LEN_PER_JOB * NJOBS);
-
- gc_job_manager_sptr mgr;
- gc_jm_options opts;
- opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa_spx);
- opts.nspes = 1;
- mgr = gc_make_job_manager(&opts);
-
-
- gc_proc_id_t gcp_qa_put_seq = mgr->lookup_proc("qa_put_seq");
-
- // do all the initialization up front
-
- for (int i = 0, val = STARTING_VAL; i < NJOBS; i++, val += 3){
- jd[i] = mgr->alloc_job_desc();
- init_jd(jd[i], gcp_qa_put_seq);
- jd[i]->input.nargs = 1;
- jd[i]->input.arg[0].s32 = val;
- jd[i]->eaa.nargs = 1;
- jd[i]->eaa.arg[0].ea_addr = ptr_to_ea(&buf[i * LEN_PER_JOB]);
- jd[i]->eaa.arg[0].direction = GCJD_DMA_PUT;
- jd[i]->eaa.arg[0].put_size = LEN_PER_JOB;
- }
-
- // submit them all
-
- for (int i = 0; i < NJOBS; i++){
- if (!mgr->submit_job(jd[i])){
- printf("%d: submit_job(jd[%2d]) failed, status = %d\n", __LINE__, i, jd[i]->status);
- }
- }
-
- // wait for them all
-
- int n = mgr->wait_jobs(NJOBS, jd, done, GC_WAIT_ALL);
- CPPUNIT_ASSERT_EQUAL(NJOBS, n);
-
- // check results
-
- for (int i = 0, val = STARTING_VAL; i < NJOBS; i++, val += 3){
- CPPUNIT_ASSERT_EQUAL(JS_OK, jd[i]->status);
- CPPUNIT_ASSERT(confirm_seq(&buf[i * LEN_PER_JOB], LEN_PER_JOB, val));
- }
-
- // cleanup
- for (int i = 0; i < NJOBS; i++)
- mgr->free_job_desc(jd[i]);
-}
-
-void
-qa_job_manager::t15_body()
-{
- gc_jm_options opts;
- opts.program_handle = gc_program_handle_from_address(&gcell_runtime_qa_spx);
- opts.nspes = 1;
- gc_job_manager_sptr mgr = gc_make_job_manager(&opts);
-
- gc_job_manager::set_singleton(mgr);
-
- CPPUNIT_ASSERT(gc_job_manager::singleton());
- mgr.reset();
- CPPUNIT_ASSERT_THROW(gc_job_manager::singleton(), boost::bad_weak_ptr);
-}
diff --git a/gcell/lib/runtime/qa_job_manager.h b/gcell/lib/runtime/qa_job_manager.h
deleted file mode 100644
index ab3325b73..000000000
--- a/gcell/lib/runtime/qa_job_manager.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef INCLUDED_QA_JOB_MANAGER_H
-#define INCLUDED_QA_JOB_MANAGER_H
-
-#include <cppunit/extensions/HelperMacros.h>
-#include <cppunit/TestCase.h>
-
-class qa_job_manager;
-typedef void (qa_job_manager::*test_t)();
-
-
-class qa_job_manager : public CppUnit::TestCase {
-
- CPPUNIT_TEST_SUITE(qa_job_manager);
- CPPUNIT_TEST(t0);
- CPPUNIT_TEST(t1);
- CPPUNIT_TEST(t2);
- CPPUNIT_TEST(t3);
- CPPUNIT_TEST(t4);
- CPPUNIT_TEST(t5);
- CPPUNIT_TEST(t6);
- CPPUNIT_TEST(t7);
- CPPUNIT_TEST(t8);
- CPPUNIT_TEST(t9);
- CPPUNIT_TEST(t10);
- CPPUNIT_TEST(t11);
- CPPUNIT_TEST(t12);
- CPPUNIT_TEST(t13);
- CPPUNIT_TEST(t14);
- CPPUNIT_TEST(t15);
- CPPUNIT_TEST_SUITE_END();
-
- private:
- void leak_check(test_t t, const std::string &name);
-
- void t0();
- void t1();
- void t1_body();
- void t2();
- void t2_body();
- void t3();
- void t3_body();
- void t4();
- void t4_body();
- void t5();
- void t5_body();
- void t6();
- void t6_body();
- void t7();
- void t7_body();
- void t8();
- void t8_body();
- void t9();
- void t9_body();
- void t10();
- void t10_body();
- void t11();
- void t11_body();
- void t12();
- void t12_body();
- void t13();
- void t13_body();
- void t14();
- void t14_body();
- void t15();
- void t15_body();
-
-};
-
-#endif /* INCLUDED_QA_JOB_MANAGER_H */
diff --git a/gcell/lib/runtime/spu/.gitignore b/gcell/lib/runtime/spu/.gitignore
deleted file mode 100644
index 36b575570..000000000
--- a/gcell/lib/runtime/spu/.gitignore
+++ /dev/null
@@ -1,10 +0,0 @@
-/Makefile
-/Makefile.in
-/*.a
-/*.la
-/*.lo
-/.deps
-/.libs
-/test_spu
-/gcell_spu_main
-/gcell_qa
diff --git a/gcell/lib/runtime/spu/gc_delay.c b/gcell/lib/runtime/spu/gc_delay.c
deleted file mode 100644
index 4d58935aa..000000000
--- a/gcell/lib/runtime/spu/gc_delay.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <gcell/spu/gc_delay.h>
-#include <gcell/compiler.h>
-
-inline static void
-gc_udelay_1us(void)
-{
- unsigned int i = 158;
-
- do { // 20 clocks per iteration of the loop
- asm ("nop $127; nop $127; nop $127; nop $127; nop $127");
- asm ("nop $127; nop $127; nop $127; nop $127; nop $127");
- asm ("nop $127; nop $127; nop $127; nop $127; nop $127");
- asm ("nop $127; nop $127");
- } while(--i != 0);
-}
-
-void
-gc_udelay(unsigned int usecs)
-{
- unsigned int i;
- for (i = 0; i < usecs; i++)
- gc_udelay_1us();
-}
-
-void
-gc_cdelay(unsigned int cpu_cycles)
-{
- if (cpu_cycles < 40) // roughly the amount of overhead
- return;
-
- cpu_cycles >>= 2; // about 4 cycles / loop
-
- while (cpu_cycles-- != 0){
- asm ("nop $127"); // keeps compiler from removing the loop
- }
-}
-
diff --git a/gcell/lib/runtime/spu/gc_logging.c b/gcell/lib/runtime/spu/gc_logging.c
deleted file mode 100644
index 48b7e5f25..000000000
--- a/gcell/lib/runtime/spu/gc_logging.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2008 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <gcell/gc_logging.h>
-#include <gcell/gc_spu_args.h>
-#include <spu_intrinsics.h>
-#include <spu_mfcio.h>
-
-static gc_eaddr_t log_base_ea; // base address of log entries in EA
-static uint32_t log_idx_mask; // nentries - 1
-static uint32_t log_idx; // current log entry index
-static uint32_t log_seqno;
-
-static int log_tags; // two consecutive tags
-static int tmp_buffer_busy; // bitmask: buffer busy state
-static int tmp_buffer_idx; // 0 or 1
-static gc_log_entry_t tmp_buffer[2];
-
-void
-_gc_log_init(gc_log_t info)
-{
- spu_write_decrementer(~0);
-
- log_base_ea = info.base;
- log_idx_mask = info.nentries - 1;
- log_idx = 0;
- log_seqno = 0;
-
- log_tags = mfc_multi_tag_reserve(2);
- tmp_buffer_busy = 0;
- tmp_buffer_idx = 0;
-
- gc_log_write0(GCL_SS_SYS, 0);
-}
-
-void
-_gc_log_write(gc_log_entry_t entry)
-{
- if (log_base_ea == 0)
- return;
-
- entry.seqno = log_seqno++;
- entry.timestamp = spu_read_decrementer();
-
- if (tmp_buffer_busy & (1 << tmp_buffer_idx)){
- mfc_write_tag_mask(1 << (log_tags + tmp_buffer_idx));
- mfc_read_tag_status_all();
- }
-
- tmp_buffer[tmp_buffer_idx] = entry; // save local copy
-
- mfc_put(&tmp_buffer[tmp_buffer_idx],
- log_base_ea + log_idx * sizeof(entry), sizeof(entry),
- log_tags + tmp_buffer_idx, 0, 0);
-
- tmp_buffer_busy |= (1 << tmp_buffer_idx);
- tmp_buffer_idx ^= 0x1;
- log_idx = (log_idx + 1) & log_idx_mask;
-}
diff --git a/gcell/lib/runtime/spu/gc_main.c b/gcell/lib/runtime/spu/gc_main.c
deleted file mode 100644
index ba56e40f6..000000000
--- a/gcell/lib/runtime/spu/gc_main.c
+++ /dev/null
@@ -1,731 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007,2008,2009 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-// #define ENABLE_GC_LOGGING // define to enable logging
-
-#include <spu_intrinsics.h>
-#include <spu_mfcio.h>
-#include <sync_utils.h>
-#include "gc_spu_config.h"
-#include "spu_buffers.h"
-#include <gcell/gc_spu_args.h>
-#include <gcell/gc_job_desc.h>
-#include <gcell/gc_mbox.h>
-#include <gcell/gc_declare_proc.h>
-#include <gcell/spu/gc_jd_queue.h>
-#include <gcell/spu/gc_random.h>
-#include <gcell/spu/gc_delay.h>
-
-#include <string.h>
-#include <assert.h>
-#include <stdio.h>
-
-
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
-//! round x down to p2 boundary (p2 must be a power-of-2)
-#define ROUND_DN(x, p2) ((x) & ~((p2)-1))
-
-//! round x up to p2 boundary (p2 must be a power-of-2)
-#define ROUND_UP(x, p2) (((x)+((p2)-1)) & ~((p2)-1))
-
-
-//#define OUT_MBOX_CHANNEL SPU_WrOutIntrMbox
-#define OUT_MBOX_CHANNEL SPU_WrOutMbox
-
-#define CHECK_QUEUE_ON_MSG 0 // define to 0 or 1
-#define USE_LLR_LOST_EVENT 0 // define to 0 or 1
-
-int gc_sys_tag; // tag for misc DMA operations
-static gc_spu_args_t spu_args;
-
-static struct gc_proc_def *gc_proc_def; // procedure entry points
-
-// ------------------------------------------------------------------------
-
-// state for DMA'ing arguments in and out
-
-static int get_tag; // 1 tag for job arg gets
-static int put_tags; // 2 tags for job arg puts
-
-static int pb_idx = 0; // current put buffer index (0 or 1)
-
-// bitmask (bit per put buffer): bit is set if DMA is started but not complete
-static int put_in_progress = 0;
-#define PBI_MASK(_pbi_) (1 << (_pbi_))
-
-// ------------------------------------------------------------------------
-
-// our working copy of the completion info
-static gc_comp_info_t comp_info = {
- .in_use = 1,
- .ncomplete = 0
-};
-
-static int ci_idx = 0; // index of current comp_info
-static int ci_tags; // two consecutive dma tags
-
-// ------------------------------------------------------------------------
-
-/*
- * Wait until EA copy of comp_info[idx].in_use is 0
- */
-static void
-wait_for_ppe_to_be_done_with_comp_info(int idx)
-{
- char _tmp[256];
- char *buf = (char *) ALIGN(_tmp, 128); // get cache-aligned buffer
- gc_comp_info_t *p = (gc_comp_info_t *) buf;
-
- assert(sizeof(gc_comp_info_t) == 128);
-
- do {
- mfc_get(buf, spu_args.comp_info[idx], 128, gc_sys_tag, 0, 0);
- mfc_write_tag_mask(1 << gc_sys_tag);
- mfc_read_tag_status_all();
- if (p->in_use == 0)
- return;
-
- gc_udelay(1);
-
- } while (1);
-}
-
-static void
-flush_completion_info(void)
-{
- // events: 0x3X
-
- static int total_complete = 0;
-
- if (comp_info.ncomplete == 0)
- return;
-
- // ensure that PPE is done with the buffer we're about to overwrite
- wait_for_ppe_to_be_done_with_comp_info(ci_idx);
-
- // dma the comp_info out to PPE
- int tag = ci_tags + ci_idx;
- mfc_put(&comp_info, spu_args.comp_info[ci_idx], sizeof(gc_comp_info_t), tag, 0, 0);
-
- // we need to wait for the completion info to finish, as well as
- // any EA argument puts.
-
- int tag_mask = 1 << tag; // the comp_info tag
- if (put_in_progress & PBI_MASK(0))
- tag_mask |= (1 << (put_tags + 0));
- if (put_in_progress & PBI_MASK(1))
- tag_mask |= (1 << (put_tags + 1));
-
- gc_log_write2(GCL_SS_SYS, 0x30, put_in_progress, tag_mask);
-
- mfc_write_tag_mask(tag_mask); // the tags we're interested in
- mfc_read_tag_status_all(); // wait for DMA to complete
- put_in_progress = 0; // mark them all complete
-
- total_complete += comp_info.ncomplete;
- gc_log_write4(GCL_SS_SYS, 0x31,
- put_in_progress, ci_idx, comp_info.ncomplete, total_complete);
-
- // send PPE a message
- spu_writech(OUT_MBOX_CHANNEL, MK_MBOX_MSG(OP_JOBS_DONE, ci_idx));
-
- ci_idx ^= 0x1; // switch buffers
- comp_info.in_use = 1;
- comp_info.ncomplete = 0;
-}
-
-// ------------------------------------------------------------------------
-
-
-static unsigned int backoff; // current backoff value in clock cycles
-static unsigned int _backoff_start;
-static unsigned int _backoff_cap;
-
-/*
- * For 3.2 GHz SPE
- *
- * 10 1023 cycles 320 ns
- * 11 2047 cycle 640 ns
- * 12 4095 cycles 1.3 us
- * 13 8191 cycles 2.6 us
- * 14 16383 cycles 5.1 us
- * 15 32767 cycles 10.2 us
- * 16 20.4 us
- * 17 40.8 us
- * 18 81.9 us
- * 19 163.8 us
- * 20 327.7 us
- * 21 655.4 us
- */
-static unsigned char log2_backoff_start[16] = {
-// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
-// -------------------------------------------------------------
-//12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 16, 16
- 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11
-};
-
-static unsigned char log2_backoff_cap[16] = {
-// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
-// -------------------------------------------------------------
-//17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 21, 21
- 13, 14, 14, 14, 14, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16
-};
-
-static void
-backoff_init(void)
-{
- _backoff_cap = (1 << (log2_backoff_cap[(spu_args.nspus - 1) & 0xf])) - 1;
- _backoff_start = (1 << (log2_backoff_start[(spu_args.nspus - 1) & 0xf])) - 1;
-
- backoff = _backoff_start;
-}
-
-#if !CHECK_QUEUE_ON_MSG
-
-static void
-backoff_reset(void)
-{
- backoff = _backoff_start;
-}
-
-
-#define RANDOM_WEIGHT 0.2
-
-static void
-backoff_delay(void)
-{
- gc_cdelay(backoff);
-
- // capped exponential backoff
- backoff = ((backoff << 1) + 1);
- if (backoff > _backoff_cap)
- backoff = _backoff_cap;
-
- // plus some randomness
- float r = (RANDOM_WEIGHT * (2.0 * (gc_uniform_deviate() - 0.5)));
- backoff = backoff * (1.0 + r);
-}
-
-#endif // !CHECK_QUEUE_ON_MSG
-
-// ------------------------------------------------------------------------
-
-static inline unsigned int
-make_mask(int nbits)
-{
- return ~(~0 << nbits);
-}
-
-static unsigned int dc_work;
-static int dc_put_tag;
-static unsigned char *dc_ls_base;
-static gc_eaddr_t dc_ea_base;
-
-// divide and conquer
-static void
-d_and_c(unsigned int offset, unsigned int len)
-{
- unsigned int mask = make_mask(len) << offset;
- unsigned int t = mask & dc_work;
- if (t == 0) // nothing to do
- return;
- if (t == mask){ // got a match, generate dma
- mfc_put(dc_ls_base + offset, dc_ea_base + offset, len, dc_put_tag, 0, 0);
- }
- else { // bisect
- len >>= 1;
- d_and_c(offset, len);
- d_and_c(offset + len, len);
- }
-}
-
-// Handle the nasty case of a dma xfer that's less than 16 bytes long.
-// len is guaranteed to be in [1, 15]
-
-static void
-handle_slow_and_tedious_dma(gc_eaddr_t ea, unsigned char *ls,
- unsigned int len, int put_tag)
-{
- // Set up for divide and conquer
- unsigned int alignment = ((uintptr_t) ls) & 0x7;
- dc_work = make_mask(len) << alignment;
- dc_ls_base = (unsigned char *) ROUND_DN((uintptr_t) ls, 8);
- dc_ea_base = ROUND_DN(ea, (gc_eaddr_t) 8);
- dc_put_tag = put_tag;
-
- d_and_c( 0, 8);
- d_and_c( 8, 8);
- d_and_c(16, 8);
-}
-
-
-static void
-process_job(gc_eaddr_t jd_ea, gc_job_desc_t *jd)
-{
- // events: 0x2X
-
- jd->status = JS_OK; // assume success
-
- if (jd->proc_id >= spu_args.nproc_defs)
- jd->status = JS_UNKNOWN_PROC;
-
- else {
-
- if (jd->eaa.nargs == 0)
- (*gc_proc_def[jd->proc_id].proc)(&jd->input, &jd->output, &jd->eaa);
-
- else { // handle EA args that must be DMA'd in/out
-
- gc_job_ea_args_t *eaa = &jd->eaa;
-
- int NELMS =
- MAX(MAX_ARGS_EA,
- (GC_SPU_BUFSIZE + MFC_MAX_DMA_SIZE - 1) / MFC_MAX_DMA_SIZE);
-
- mfc_list_element_t dma_get_list[NELMS];
- //mfc_list_element_t dma_put_list[NELMS];
-
- memset(dma_get_list, 0, sizeof(dma_get_list));
- //memset(dma_put_list, 0, sizeof(dma_put_list));
-
- int gli = 0; // get list index
- //int pli = 0; // put list index
-
- unsigned char *get_base = _gci_getbuf[0];
- unsigned char *get_t = get_base;
- unsigned int total_get_dma_len = 0;
-
- unsigned char *put_base = _gci_putbuf[pb_idx];
- unsigned char *put_t = put_base;
- unsigned int total_put_alloc = 0;
- int put_tag = put_tags + pb_idx;
-
- // Do we have any "put" args? If so ensure that previous
- // dma from this buffer is complete
-
- gc_log_write2(GCL_SS_SYS, 0x24, put_in_progress, jd->sys.direction_union);
-
- if ((jd->sys.direction_union & GCJD_DMA_PUT)
- && (put_in_progress & PBI_MASK(pb_idx))){
-
- gc_log_write2(GCL_SS_SYS, 0x25, put_in_progress, 1 << put_tag);
-
- mfc_write_tag_mask(1 << put_tag); // the tag we're interested in
- mfc_read_tag_status_all(); // wait for DMA to complete
- put_in_progress &= ~(PBI_MASK(pb_idx));
-
- gc_log_write1(GCL_SS_SYS, 0x26, put_in_progress);
- }
-
-
- // for now, all EA's must have the same high 32-bits
- gc_eaddr_t common_ea = eaa->arg[0].ea_addr;
-
-
- // assign LS addresses for buffers
-
- for (unsigned int i = 0; i < eaa->nargs; i++){
-
- gc_eaddr_t ea_base = 0;
- unsigned char *ls_base;
- int offset;
- unsigned int dma_len;
-
- if (eaa->arg[i].direction == GCJD_DMA_GET){
- ea_base = ROUND_DN(eaa->arg[i].ea_addr, (gc_eaddr_t) CACHE_LINE_SIZE);
- offset = eaa->arg[i].ea_addr & (CACHE_LINE_SIZE-1);
- dma_len = ROUND_UP(eaa->arg[i].get_size + offset, CACHE_LINE_SIZE);
- total_get_dma_len += dma_len;
-
- if (total_get_dma_len > GC_SPU_BUFSIZE){
- jd->status = JS_ARGS_TOO_LONG;
- goto wrap_up;
- }
-
- ls_base = get_t;
- get_t += dma_len;
- eaa->arg[i].ls_addr = ls_base + offset;
-
- if (0){
- assert((mfc_ea2l(eaa->arg[i].ea_addr) & 0x7f) == ((intptr_t)eaa->arg[i].ls_addr & 0x7f));
- assert((ea_base & 0x7f) == 0);
- assert(((intptr_t)ls_base & 0x7f) == 0);
- assert((dma_len & 0x7f) == 0);
- assert((eaa->arg[i].get_size <= dma_len)
- && dma_len <= (eaa->arg[i].get_size + offset + CACHE_LINE_SIZE - 1));
- }
-
- // add to dma get list
- // FIXME (someday) the dma list is where the JS_BAD_EAH limitation comes from
-
- while (dma_len != 0){
- int n = MIN(dma_len, MFC_MAX_DMA_SIZE);
- dma_get_list[gli].size = n;
- dma_get_list[gli].eal = mfc_ea2l(ea_base);
- dma_len -= n;
- ea_base += n;
- gli++;
- }
- }
-
- else if (eaa->arg[i].direction == GCJD_DMA_PUT){
- //
- // This case is a trickier than the PUT case since we can't
- // write outside of the bounds of the user provided buffer.
- // We still align the buffers to 128-bytes for good performance
- // in the middle portion of the xfers.
- //
- ea_base = ROUND_DN(eaa->arg[i].ea_addr, (gc_eaddr_t) CACHE_LINE_SIZE);
- offset = eaa->arg[i].ea_addr & (CACHE_LINE_SIZE-1);
-
- uint32_t ls_alloc_len =
- ROUND_UP(eaa->arg[i].put_size + offset, CACHE_LINE_SIZE);
-
- total_put_alloc += ls_alloc_len;
-
- if (total_put_alloc > GC_SPU_BUFSIZE){
- jd->status = JS_ARGS_TOO_LONG;
- goto wrap_up;
- }
-
- ls_base = put_t;
- put_t += ls_alloc_len;
- eaa->arg[i].ls_addr = ls_base + offset;
-
- if (1){
- assert((mfc_ea2l(eaa->arg[i].ea_addr) & 0x7f)
- == ((intptr_t)eaa->arg[i].ls_addr & 0x7f));
- assert((ea_base & 0x7f) == 0);
- assert(((intptr_t)ls_base & 0x7f) == 0);
- }
- }
-
- else
- assert(0);
- }
-
- // fire off the dma to fetch the args and wait for it to complete
- mfc_getl(get_base, common_ea, dma_get_list, gli*sizeof(dma_get_list[0]), get_tag, 0, 0);
- mfc_write_tag_mask(1 << get_tag); // the tag we're interested in
- mfc_read_tag_status_all(); // wait for DMA to complete
-
- // do the work
- (*gc_proc_def[jd->proc_id].proc)(&jd->input, &jd->output, &jd->eaa);
-
-
- // Do we have any "put" args? If so copy them out
- if (jd->sys.direction_union & GCJD_DMA_PUT){
-
- // Do the copy out using single DMA xfers. The LS ranges
- // aren't generally contiguous.
-
- bool started_dma = false;
-
- for (unsigned int i = 0; i < eaa->nargs; i++){
- if (eaa->arg[i].direction == GCJD_DMA_PUT && eaa->arg[i].put_size != 0){
-
- started_dma = true;
-
- gc_eaddr_t ea;
- unsigned char *ls;
- unsigned int len;
-
- ea = eaa->arg[i].ea_addr;
- ls = (unsigned char *) eaa->arg[i].ls_addr;
- len = eaa->arg[i].put_size;
-
- if (len < 16)
- handle_slow_and_tedious_dma(ea, ls, len, put_tag);
-
- else {
- if ((ea & 0xf) != 0){
-
- // printf("1: ea = 0x%x len = %5d\n", (int) ea, len);
-
- // handle the "pre-multiple-of-16" portion
- // do 1, 2, 4, or 8 byte xfers as required
-
- if (ea & 0x1){ // do a 1-byte xfer
- mfc_put(ls, ea, 1, put_tag, 0, 0);
- ea += 1;
- ls += 1;
- len -= 1;
- }
- if (ea & 0x2){ // do a 2-byte xfer
- mfc_put(ls, ea, 2, put_tag, 0, 0);
- ea += 2;
- ls += 2;
- len -= 2;
- }
- if (ea & 0x4){ // do a 4-byte xfer
- mfc_put(ls, ea, 4, put_tag, 0, 0);
- ea += 4;
- ls += 4;
- len -= 4;
- }
- if (ea & 0x8){ // do an 8-byte xfer
- mfc_put(ls, ea, 8, put_tag, 0, 0);
- ea += 8;
- ls += 8;
- len -= 8;
- }
- }
-
- if (1){
- // printf("2: ea = 0x%x len = %5d\n", (int) ea, len);
- assert((ea & 0xf) == 0);
- assert((((intptr_t) ls) & 0xf) == 0);
- }
-
- // handle the "multiple-of-16" portion
-
- int aligned_len = ROUND_DN(len, 16);
- len = len & (16 - 1);
-
- while (aligned_len != 0){
- int dma_len = MIN(aligned_len, MFC_MAX_DMA_SIZE);
- mfc_put(ls, ea, dma_len, put_tag, 0, 0);
- ea += dma_len;
- ls += dma_len;
- aligned_len -= dma_len;
- }
-
- if (1){
- // printf("3: ea = 0x%x len = %5d\n", (int)ea, len);
- assert((ea & 0xf) == 0);
- assert((((intptr_t) ls) & 0xf) == 0);
- }
-
- // handle "post-multiple-of-16" portion
-
- if (len != 0){
-
- if (len >= 8){ // do an 8-byte xfer
- mfc_put(ls, ea, 8, put_tag, 0, 0);
- ea += 8;
- ls += 8;
- len -= 8;
- }
- if (len >= 4){ // do a 4-byte xfer
- mfc_put(ls, ea, 4, put_tag, 0, 0);
- ea += 4;
- ls += 4;
- len -= 4;
- }
- if (len >= 2){ // do a 2-byte xfer
- mfc_put(ls, ea, 2, put_tag, 0, 0);
- ea += 2;
- ls += 2;
- len -= 2;
- }
- if (len >= 1){ // do a 1-byte xfer
- mfc_put(ls, ea, 1, put_tag, 0, 0);
- ea += 1;
- ls += 1;
- len -= 1;
- }
- if (1)
- assert(len == 0);
- }
- }
- }
- }
- if (started_dma){
- put_in_progress |= PBI_MASK(pb_idx); // note it's running
- gc_log_write2(GCL_SS_SYS, 0x27, put_in_progress, pb_idx);
- pb_idx ^= 1; // toggle current buffer
- }
- }
- }
- }
-
- wrap_up:; // semicolon creates null statement for C99 compliance
-
- // Copy job descriptor back out to EA.
- // (The dma will be waited on in flush_completion_info)
- int tag = ci_tags + ci_idx; // use the current completion tag
- mfc_put(jd, jd_ea, sizeof(*jd), tag, 0, 0);
-
- // Tell PPE we're done with the job.
- //
- // We queue these up until we run out of room, or until we can send
- // the info to the PPE w/o blocking. The blocking check is in
- // main_loop
-
- comp_info.job_id[comp_info.ncomplete++] = jd->sys.job_id;
-
- if (comp_info.ncomplete == GC_CI_NJOBS){
- gc_log_write0(GCL_SS_SYS, 0x28);
- flush_completion_info();
- }
-}
-
-static void
-main_loop(void)
-{
- // events: 0x1X
-
- static gc_job_desc_t jd; // static gets us proper alignment
- gc_eaddr_t jd_ea;
- int total_jobs = 0;
-
-#if (USE_LLR_LOST_EVENT)
- // setup events
- spu_writech(SPU_WrEventMask, MFC_LLR_LOST_EVENT);
-
- // prime the pump
- while (gc_jd_queue_dequeue(spu_args.queue, &jd_ea, ci_tags + ci_idx, &jd))
- process_job(jd_ea, &jd);
- // we're now holding a lock-line reservation
-#endif
-
- while (1){
-
-#if !CHECK_QUEUE_ON_MSG
-#if (USE_LLR_LOST_EVENT)
-
- if (unlikely(spu_readchcnt(SPU_RdEventStat))){
- //
- // execute standard event handling prologue
- //
- int status = spu_readch(SPU_RdEventStat);
- int mask = spu_readch(SPU_RdEventMask);
- spu_writech(SPU_WrEventMask, mask & ~status); // disable active events
- spu_writech(SPU_WrEventAck, status); // ack active events
-
- // execute per-event actions
-
- if (status & MFC_LLR_LOST_EVENT){
- //
- // We've lost a line reservation. This is most likely caused
- // by somebody doing something to the queue. Go look and see
- // if there's anything for us.
- //
- while (gc_jd_queue_dequeue(spu_args.queue, &jd_ea, ci_tags + ci_idx, &jd) == GCQ_OK)
- process_job(jd_ea, &jd);
- }
-
- //
- // execute standard event handling epilogue
- //
- spu_writech(SPU_WrEventMask, mask); // restore event mask
- }
-
-#else
-
- // try to get a job from the job queue
- if (gc_jd_queue_dequeue(spu_args.queue, &jd_ea, ci_tags + ci_idx, &jd) == GCQ_OK){
- total_jobs++;
- gc_log_write2(GCL_SS_SYS, 0x10, jd.sys.job_id, total_jobs);
-
- process_job(jd_ea, &jd);
-
- gc_log_write2(GCL_SS_SYS, 0x11, jd.sys.job_id, total_jobs);
- backoff_reset();
- }
- else
- backoff_delay();
-
-#endif
-#endif
-
- // any msgs for us?
-
- if (unlikely(spu_readchcnt(SPU_RdInMbox))){
- int msg = spu_readch(SPU_RdInMbox);
- // printf("spu[%d] mbox_msg: 0x%08x\n", spu_args.spu_idx, msg);
-#if CHECK_QUEUE_ON_MSG
- if (MBOX_MSG_OP(msg) == OP_CHECK_QUEUE){
-
- while (1){
- //int delay = (int)(3200.0 * gc_uniform_deviate()); // uniformly in [0, 1.0us]
- //gc_cdelay(delay);
-
- gc_dequeue_status_t s =
- gc_jd_queue_dequeue(spu_args.queue, &jd_ea, ci_tags + ci_idx, &jd);
-
- if (s == GCQ_OK){
- total_jobs++;
- gc_log_write2(GCL_SS_SYS, 0x10, jd.sys.job_id, total_jobs);
-
- process_job(jd_ea, &jd);
-
- gc_log_write2(GCL_SS_SYS, 0x11, jd.sys.job_id, total_jobs);
- }
- else if (s == GCQ_EMPTY){
- break;
- }
- else { // GCQ_LOCKED -- keep trying
- }
- }
- }
- else
-#endif
- if (MBOX_MSG_OP(msg) == OP_EXIT){
- flush_completion_info();
- return;
- }
- else if (MBOX_MSG_OP(msg) == OP_GET_SPU_BUFSIZE){
- spu_writech(SPU_WrOutIntrMbox, MK_MBOX_MSG(OP_SPU_BUFSIZE, GC_SPU_BUFSIZE_BASE));
- }
- }
-
- // If we've got job completion info for the PPE and we can send a
- // message without blocking, do it.
-
- if (comp_info.ncomplete != 0 && spu_readchcnt(OUT_MBOX_CHANNEL) != 0){
- gc_log_write0(GCL_SS_SYS, 0x12);
- flush_completion_info();
- }
- }
-}
-
-
-int
-main(unsigned long long spe_id __attribute__((unused)),
- unsigned long long argp,
- unsigned long long envp __attribute__((unused)))
-{
- gc_sys_tag = mfc_tag_reserve(); // allocate a tag for our misc DMA operations
- get_tag = mfc_tag_reserve();
- ci_tags = mfc_multi_tag_reserve(2);
- put_tags = mfc_multi_tag_reserve(2);
-
- // dma the args in
- mfc_get(&spu_args, argp, sizeof(spu_args), gc_sys_tag, 0, 0);
- mfc_write_tag_mask(1 << gc_sys_tag); // the tag we're interested in
- mfc_read_tag_status_all(); // wait for DMA to complete
-
- // initialize pointer to procedure entry table
- gc_proc_def = (gc_proc_def_t *) spu_args.proc_def_ls_addr;
-
- gc_set_seed(spu_args.spu_idx);
-
- // initialize logging
- _gc_log_init(spu_args.log);
-
- backoff_init(); // initialize backoff parameters
-
- main_loop();
- return 0;
-}
diff --git a/gcell/lib/runtime/spu/gc_random.c b/gcell/lib/runtime/spu/gc_random.c
deleted file mode 100644
index ae2fde875..000000000
--- a/gcell/lib/runtime/spu/gc_random.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2008,2009 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#include <gcell/spu/gc_random.h>
-
-static int last_val = 0;
-
-# define M 259200 // values from Numerical Recipes in C, 1988
-# define A 7141
-# define C 54773
-
-void
-gc_set_seed(int seed)
-{
- last_val = ((unsigned int) seed) % M;
-}
-
-/*
- * Return a uniformly distributed value in the range [0, 1.0)
- * (Linear congruential generator. YMMV. Caveat emptor.)
- */
-float
-gc_uniform_deviate(void)
-{
- last_val = (last_val * A + C) % M;
- return (float) last_val * (1.0f / (float) M);
-}
diff --git a/gcell/lib/runtime/spu/gc_spu_config.h b/gcell/lib/runtime/spu/gc_spu_config.h
deleted file mode 100644
index 6320e6dbe..000000000
--- a/gcell/lib/runtime/spu/gc_spu_config.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* -*- c -*- */
-/*
- * Copyright 2008,2009 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef INCLUDED_GCELL_GC_SPU_CONFIG_H
-#define INCLUDED_GCELL_GC_SPU_CONFIG_H
-
-#include <gcell/gc_job_desc.h>
-
-#define CACHE_LINE_SIZE 128 // in bytes
-
-#if 1
-# define GC_SPU_BUFSIZE_BASE (40 * 1024) // must be multiple of CACHE_LINE_SIZE
-#else
-# define GC_SPU_BUFSIZE_BASE (20 * 1024) // must be multiple of CACHE_LINE_SIZE
-#endif
-
-#define GC_SPU_BUFSIZE (GC_SPU_BUFSIZE_BASE + MAX_ARGS_EA * CACHE_LINE_SIZE)
-
-#define NGETBUFS 1 // gets are single buffered
-#define NPUTBUFS 2 // puts are double buffered
-
-#endif /* INCLUDED_GCELL_GC_SPU_CONFIG_H */
diff --git a/gcell/lib/runtime/spu/gc_spu_jd_queue.c b/gcell/lib/runtime/spu/gc_spu_jd_queue.c
deleted file mode 100644
index 91bb5bc7e..000000000
--- a/gcell/lib/runtime/spu/gc_spu_jd_queue.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007,2008,2009 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <gcell/spu/gc_jd_queue.h>
-#include <gcell/spu/gc_delay.h>
-#include <gcell/spu/gc_random.h>
-#include "mutex_lock.h"
-#include "mutex_unlock.h"
-
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-
-extern int gc_sys_tag;
-
-// keep track of stats
-int jdq_ok;
-int jdq_empty;
-int jdq_locked;
-
-
-#define INITIAL_BACKOFF 32.0
-#define MAX_BACKOFF 8192.0 /* 2.6us */
-#define RANDOM_WEIGHT 0.2
-
-static float
-next_backoff(float backoff)
-{
- // exponential with random
- float t = backoff * 2.0;
- if (t > MAX_BACKOFF)
- t = MAX_BACKOFF;
-
- float r = (RANDOM_WEIGHT * (2.0 * (gc_uniform_deviate() - 0.5)));
- t = t * (1.0 + r);
-
- return t;
-}
-
-gc_dequeue_status_t
-gc_jd_queue_dequeue(gc_eaddr_t q, gc_eaddr_t *item_ea,
- int jd_tag, gc_job_desc_t *item)
-{
- int status;
- char _tmp[256];
- gc_jd_queue_t *local_q =
- (gc_jd_queue_t *) ALIGN(_tmp, 128); // get cache-aligned buffer
-
- float backoff = next_backoff(INITIAL_BACKOFF);
-
- do {
- // Copy the queue structure in and get a lock line reservation.
- // (The structure is 128-byte aligned and completely fills a cache-line)
-
- mfc_getllar(local_q, q, 0, 0);
- spu_readch(MFC_RdAtomicStat);
-
- if (local_q->mutex != 0){ // somebody else has it locked
- jdq_locked++;
- return GCQ_LOCKED;
- }
-
- if (local_q->head == 0){ // the queue is empty
- jdq_empty++;
- return GCQ_EMPTY;
- }
-
- // Try to acquire the lock
-
- local_q->mutex = 1;
- mfc_putllc(local_q, q, 0, 0);
- status = spu_readch(MFC_RdAtomicStat);
-
- if (status != 0){
- gc_cdelay((int) backoff);
- backoff = next_backoff(backoff);
- }
-
- } while (status != 0);
-
- // we're now holding the lock
-
- // copy in job descriptor at head of queue
- *item_ea = local_q->head;
-
- // We must use the fence with the jd_tag to ensure that any
- // previously initiated put of a job desc is locally ordered before
- // the get of the new one.
- mfc_getf(item, local_q->head, sizeof(gc_job_desc_t), jd_tag, 0, 0);
- mfc_write_tag_mask(1 << jd_tag); // the tag we're interested in
- mfc_read_tag_status_all(); // wait for DMA to complete
-
- local_q->head = item->sys.next;
- item->sys.next = 0;
- if (local_q->head == 0) // now empty?
- local_q->tail = 0;
-
- // Copy the queue struct back out and unlock the mutex in one fell swoop.
- // We use the unconditional put since it's faster and we own the lock.
-
- local_q->mutex = 0;
- mfc_putlluc(local_q, q, 0, 0);
- spu_readch(MFC_RdAtomicStat);
-
- jdq_ok++;
- return GCQ_OK;
-}
diff --git a/gcell/lib/runtime/spu/gcell_runtime_qa.c b/gcell/lib/runtime/spu/gcell_runtime_qa.c
deleted file mode 100644
index 47a4b5b5b..000000000
--- a/gcell/lib/runtime/spu/gcell_runtime_qa.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2008 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <gcell/gc_declare_proc.h>
-#include <gcell/spu/gc_delay.h>
-#include <string.h>
-
-
-static void
-qa_nop(const gc_job_direct_args_t *input _UNUSED,
- gc_job_direct_args_t *output _UNUSED,
- const gc_job_ea_args_t *eaa _UNUSED)
-{
-}
-
-GC_DECLARE_PROC(qa_nop, "qa_nop");
-
-static int
-sum_shorts(short *p, int nshorts)
-{
- int total = 0;
- for (int i = 0; i < nshorts; i++)
- total += p[i];
-
- return total;
-}
-
-static void
-qa_sum_shorts(const gc_job_direct_args_t *input _UNUSED,
- gc_job_direct_args_t *output,
- const gc_job_ea_args_t *eaa)
-{
- for (unsigned int i = 0; i < eaa->nargs; i++){
- short *p = eaa->arg[i].ls_addr;
- int n = eaa->arg[i].get_size / sizeof(short);
- output->arg[i].s32 = sum_shorts(p, n);
- //printf("qa_sum_shorts(%p, %d) = %d\n", p, n, output->arg[i].s32);
- }
-}
-
-GC_DECLARE_PROC(qa_sum_shorts, "qa_sum_shorts");
-
-static void
-write_seq(unsigned char *p, int nbytes, int counter)
-{
- for (int i = 0; i < nbytes; i++)
- p[i] = counter++;
-}
-
-static void
-qa_put_seq(const gc_job_direct_args_t *input,
- gc_job_direct_args_t *output _UNUSED,
- const gc_job_ea_args_t *eaa)
-{
- int counter = input->arg[0].s32;
-
- for (unsigned int i = 0; i < eaa->nargs; i++){
- unsigned char *p = eaa->arg[i].ls_addr;
- int n = eaa->arg[i].put_size;
- write_seq(p, n, counter);
- counter += n;
- }
-}
-
-GC_DECLARE_PROC(qa_put_seq, "qa_put_seq");
-
-static void
-qa_copy(const gc_job_direct_args_t *input _UNUSED,
- gc_job_direct_args_t *output,
- const gc_job_ea_args_t *eaa)
-{
- if (eaa->nargs != 2
- || eaa->arg[0].direction != GCJD_DMA_PUT
- || eaa->arg[1].direction != GCJD_DMA_GET){
- output->arg[0].s32 = -1;
- return;
- }
-
- output->arg[0].s32 = 0;
- unsigned n = eaa->arg[0].put_size;
- if (eaa->arg[1].get_size < n)
- n = eaa->arg[1].get_size;
-
- memcpy(eaa->arg[0].ls_addr, eaa->arg[1].ls_addr, n);
-}
-
-GC_DECLARE_PROC(qa_copy, "qa_copy");
diff --git a/gcell/lib/runtime/spu/spu_buffers.c b/gcell/lib/runtime/spu/spu_buffers.c
deleted file mode 100644
index 29ae99d9f..000000000
--- a/gcell/lib/runtime/spu/spu_buffers.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2008 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "spu_buffers.h"
-#include <gcell/compiler.h>
-
-static unsigned char _getbuf[NGETBUFS][GC_SPU_BUFSIZE] _AL128;
-static unsigned char _putbuf[NPUTBUFS][GC_SPU_BUFSIZE] _AL128;
-
-unsigned char *_gci_getbuf[NGETBUFS] = {
- _getbuf[0]
-};
-
-unsigned char *_gci_putbuf[NPUTBUFS] = {
- _putbuf[0],
- _putbuf[1]
-};
diff --git a/gcell/lib/runtime/spu/spu_buffers.h b/gcell/lib/runtime/spu/spu_buffers.h
deleted file mode 100644
index 24811dc38..000000000
--- a/gcell/lib/runtime/spu/spu_buffers.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2008 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef INCLUDED_SPU_BUFFERS_H
-#define INCLUDED_SPU_BUFFERS_H
-
-#include "gc_spu_config.h"
-
-//! pointer to input buffer
-extern unsigned char *_gci_getbuf[NGETBUFS];
-
-//! pointers to output buffers
-extern unsigned char *_gci_putbuf[NPUTBUFS];
-
-#endif /* INCLUDED_SPU_BUFFERS_H */