commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] r7021 - in gnuradio/branches/developers/eb/gcell/src:


From: eb
Subject: [Commit-gnuradio] r7021 - in gnuradio/branches/developers/eb/gcell/src: include lib
Date: Sun, 25 Nov 2007 01:24:13 -0700 (MST)

Author: eb
Date: 2007-11-25 01:24:13 -0700 (Sun, 25 Nov 2007)
New Revision: 7021

Added:
   gnuradio/branches/developers/eb/gcell/src/include/gc_spu_args.h
Modified:
   gnuradio/branches/developers/eb/gcell/src/lib/gc_job_manager_impl.cc
   gnuradio/branches/developers/eb/gcell/src/lib/gc_job_manager_impl.h
Log:
work-in-progress on cell job manager.  Time to write some SPE code ;)

Added: gnuradio/branches/developers/eb/gcell/src/include/gc_spu_args.h
===================================================================
--- gnuradio/branches/developers/eb/gcell/src/include/gc_spu_args.h             
                (rev 0)
+++ gnuradio/branches/developers/eb/gcell/src/include/gc_spu_args.h     
2007-11-25 08:24:13 UTC (rev 7021)
@@ -0,0 +1,34 @@
+/* -*- 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_GC_SPU_ARGS_H
+#define INCLUDED_GC_SPU_ARGS_H
+
+#include <gc_types.h>
+
+// args passed to SPU at initialization time
+
+typedef struct gc_spu_args {
+  gc_eaddr_t   queue;          // address of job queue
+  uint32_t     spu_idx;        // which spu we are: [0,nspus-1]
+  uint32_t     _pad;
+} _AL16 gc_spu_args_t;
+
+#endif /* INCLUDED_GC_SPU_ARGS_H */


Property changes on: 
gnuradio/branches/developers/eb/gcell/src/include/gc_spu_args.h
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: gnuradio/branches/developers/eb/gcell/src/lib/gc_job_manager_impl.cc
===================================================================
--- gnuradio/branches/developers/eb/gcell/src/lib/gc_job_manager_impl.cc        
2007-11-25 02:48:29 UTC (rev 7020)
+++ gnuradio/branches/developers/eb/gcell/src/lib/gc_job_manager_impl.cc        
2007-11-25 08:24:13 UTC (rev 7021)
@@ -60,21 +60,26 @@
 /*
  * Return pointer to cache-aligned chunk of storage of size size bytes.
  * Throw if can't allocate memory.  The storage should be freed
- * using "free" when done.
+ * with "free" when done.  The memory is initialized to zero.
  */
 static void *
-aligned_alloc(size_t size)
+aligned_alloc(size_t size, size_t alignment = CACHE_LINE_SIZE)
 {
   void *p = 0;
-  if (posix_memalign(&p, CACHE_LINE_SIZE, size) != 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;
 }
 
+////////////////////////////////////////////////////////////////////////
+
+
 gc_job_manager_impl::gc_job_manager_impl(const gc_jm_options *options)
-  : d_eh_cond(&d_eh_mutex), d_eh_thread(0), d_eh_state(EHS_INIT),
+  : d_spu_args(0),
+    d_eh_cond(&d_eh_mutex), d_eh_thread(0), d_eh_state(EHS_INIT),
     d_shutdown_requested(false),
     d_nclients(0), d_client_thread(0), d_job_busy(0)
 {
@@ -119,6 +124,10 @@
        // 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;
+      }
     }
   }
 
@@ -134,9 +143,27 @@
     }
   }
 
+  // ----------------------------------------------------------------
+  // initalize the job queue
+  
+  d_queue = (gc_jd_queue_t *) aligned_alloc(sizeof(gc_jd_queue_t));
+  _d_queue_boost =
+    boost::shared_ptr<void>((void *) d_queue, free_deleter());
+  gc_jd_queue_init(d_queue);
+
+
+  // ----------------------------------------------------------------
   // create the spe contexts
 
-  int spe_flags = SPE_EVENTS_ENABLE | SPE_CFG_SIGNOTIFY1_OR | 
SPE_CFG_SIGNOTIFY2_OR;
+  assert(sizeof(gc_spu_args_t) % 16 == 0);
+  d_spu_args =
+    (gc_spu_args_t *) aligned_alloc(MAX_SPES * sizeof(gc_spu_args_t), 16);
+  _d_spu_args_boost =
+    boost::shared_ptr<void>((void *) d_spu_args, free_deleter());
+
+  int spe_flags = (SPE_EVENTS_ENABLE
+                  | SPE_CFG_SIGNOTIFY1_OR
+                  | SPE_CFG_SIGNOTIFY2_OR);
   
   for (unsigned int i = 0; i < d_options.nspes; i++){
     // FIXME affinity stuff goes here
@@ -145,6 +172,10 @@
       perror("spe_context_create");
       throw std::runtime_error("spe_context_create");
     }
+    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->spu_idx = i;
     d_worker[i].state = WS_INIT;
 
     // FIXME load some code in the SPE
@@ -167,7 +198,6 @@
   // Initialize the array of job descriptors.
   d_jd = (gc_job_desc_t *) aligned_alloc(sizeof(d_jd[0]) * d_options.max_jobs);
   _d_jd_boost = boost::shared_ptr<void>((void *) d_jd, free_deleter());
-  memset(d_jd, 0, sizeof(d_jd[0]) * d_options.max_jobs);
 
 
   // set unique job_id
@@ -179,15 +209,6 @@
     free_job_desc(&d_jd[i]);
 
   // ----------------------------------------------------------------
-  // initalize the job queue
-  
-  d_queue = (gc_jd_queue_t *) aligned_alloc(sizeof(gc_jd_queue_t));
-  _d_queue_boost =
-    boost::shared_ptr<void>((void *) d_queue, free_deleter());
-  gc_jd_queue_init(d_queue);
-
-
-  // ----------------------------------------------------------------
   // initialize d_client_thread
 
   // FIXME robust deletion
@@ -205,7 +226,6 @@
   size_t byte_size = nlongs * sizeof(unsigned long);
   void *p = aligned_alloc(byte_size);
   _d_all_bitvectors = boost::shared_ptr<void>(p, free_deleter());
-  memset(p, 0, byte_size);
 
   // now point the other pointers into this storage.
   // d_job_busy is the first one, followed by the ones in the client data
@@ -218,16 +238,14 @@
     d_client_thread[i].d_jobs_were_waiting_for = v;
 
   // ----------------------------------------------------------------
-  // create the spe event handler
+  // create the spe event handler & worker (SPE) threads
 
   create_event_handler();
 
-  // FIXME create N worker threads
-  // FIXME confirm everything started OK
-
-  // Done!
 }
 
+////////////////////////////////////////////////////////////////////////
+
 gc_job_manager_impl::~gc_job_manager_impl()
 {
   shutdown();
@@ -296,6 +314,35 @@
   return false;                        // FIXME
 }
 
+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;
+}
+
+////////////////////////////////////////////////////////////////////////
+
 static void
 pthread_create_failure_msg(int r, const char *which)
 {
@@ -339,8 +386,10 @@
 }
 
 
+////////////////////////////////////////////////////////////////////////
 
-//extern "C" 
+static void *start_worker(void *arg);
+
 static void *
 start_event_handler(void *arg)
 {
@@ -349,24 +398,6 @@
   return 0;
 }
 
-//extern "C" 
-static void *
-worker_loop(void *arg)
-{
-  // FIXME need to pass additional info.
-  
-  worker_ctx *w = (worker_ctx *) arg;
-
-  w->state = WS_RUNNING;
-
-  printf("worker running\n");
-
-  // FIXME spe_context_run
-
-  w->state = WS_DEAD;
-  return 0;
-}
-
 void
 gc_job_manager_impl::create_event_handler()
 {
@@ -403,7 +434,7 @@
   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, worker_loop,
+    ok &= start_thread(&d_worker[i].thread, start_worker,
                       &d_worker[i], name);
   }
 
@@ -411,7 +442,7 @@
     //
     // FIXME Clean up the mess.  Need to terminate event handler and all 
workers.
     //
-    // this should cause the workers to exit, unless they're really broken
+    // this should cause the workers to exit, unless they're seriously broken
     send_all_spes(MK_MBOX_MSG(OP_EXIT, 0));
 
     shutdown();
@@ -421,33 +452,8 @@
   }
 }
 
-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::set_eh_state(evt_handler_state s)
 {
@@ -623,11 +629,68 @@
   }
 }
 
-// ------------------------------------------------------------------------
+////////////////////////////////////////////////////////////////////////
+// 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;
+  printf("worker[%d]: WS_RUNNING\n", w->spe_idx);
+
+  struct uregs {
+    gc_eaddr_t r3;          // Always pass pointers as 64-bit addresses
+    uint64_t   _pad_r3;     // in preferred slot.  Pad bottom half of reg.
+    gc_eaddr_t r4;
+    uint64_t   _pad_r4;
+    gc_eaddr_t r5;
+    uint64_t   _pad_r5;
+  } args;
+
+  assert(sizeof(args) == 48);
+
+  memset(&args, 0, sizeof(args));
+  args.r3 = ptr_to_ea(w->spe_ctx);
+  args.r4 = ptr_to_ea(w->spu_args);
+
+  unsigned int entry = SPE_DEFAULT_ENTRY;
+  int r = spe_context_run(w->spe_ctx,  &entry,
+                         SPE_RUN_USER_REGS, &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.
+    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 ;)
+  printf("worker[%d]: WS_DEAD\n", w->spe_idx);
+
+  w->state = WS_DEAD;
+  return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+
+
 worker_ctx::~worker_ctx()
 {
-  // fprintf(stderr, "\n~worker_ctx\n");
   if (spe_ctx){
     int r = spe_context_destroy(spe_ctx);
     if (r != 0){
@@ -637,4 +700,3 @@
   }
   state = WS_FREE;
 }
-

Modified: gnuradio/branches/developers/eb/gcell/src/lib/gc_job_manager_impl.h
===================================================================
--- gnuradio/branches/developers/eb/gcell/src/lib/gc_job_manager_impl.h 
2007-11-25 02:48:29 UTC (rev 7020)
+++ gnuradio/branches/developers/eb/gcell/src/lib/gc_job_manager_impl.h 
2007-11-25 08:24:13 UTC (rev 7021)
@@ -26,6 +26,7 @@
 #include "gc_client_thread_info.h"
 #include "gc_jd_stack.h"
 #include "gc_jd_queue.h"
+#include "gc_spu_args.h"
 #include <libspe2.h>
 #include <vector>
 #include <boost/shared_ptr.hpp>
@@ -42,10 +43,14 @@
 
 struct worker_ctx {
   volatile worker_state        state;
+  unsigned int         spe_idx;        // [0, nspes-1]
   spe_context_ptr_t    spe_ctx;
   pthread_t            thread;
+  gc_spu_args_t                *spu_args;      // pointer to 16-byte aligned 
struct
 
-  worker_ctx() : state(WS_FREE), spe_ctx(0), thread(0) {}
+  worker_ctx()
+    : state(WS_FREE), spe_idx(0), spe_ctx(0),
+      thread(0), spu_args(0) {}
   ~worker_ctx();
 };
 
@@ -84,6 +89,8 @@
   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
 
   // used to coordinate communication w/ the event handling thread
   omni_mutex            d_eh_mutex;





reply via email to

[Prev in Thread] Current Thread [Next in Thread]