Imported Upstream version 3.2.2
[debian/gnuradio] / gcell / include / gcell / gc_job_manager.h
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2007,2008 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio
6  * 
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  * 
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #ifndef INCLUDED_GC_JOB_MANAGER_H
23 #define INCLUDED_GC_JOB_MANAGER_H
24
25 #include <boost/utility.hpp>
26 #include <boost/shared_ptr.hpp>
27 #include <vector>
28 #include <string>
29 #include <stdexcept>
30 #include <libspe2.h>
31 #include "gc_job_desc.h"
32
33 class gc_job_manager;
34 typedef boost::shared_ptr<gc_job_manager> gc_job_manager_sptr;
35 typedef boost::shared_ptr<spe_program_handle_t> spe_program_handle_sptr;
36 typedef boost::shared_ptr<gc_job_desc> gc_job_desc_sptr;
37
38 /*!
39  * \brief Return a boost::shared_ptr to an spe_program_handle_t
40  *
41  * \param filename is the name of the SPE ELF executable to open.
42  *
43  * Calls spe_image_open to open the file.  If successful returns a
44  * boost::shared_ptr that will call spe_image_close when it's time to
45  * free the object.
46  *
47  * Returns the equivalent of the NULL pointer if the file cannot be
48  * opened, or if it's not an SPE ELF object file.
49  *
50  * \sa gc_program_handle_from_address
51  */
52 spe_program_handle_sptr 
53 gc_program_handle_from_filename(const std::string &filename);
54
55 /*!
56  * \brief Return a boost::shared_ptr to an spe_program_handle_t
57  *
58  * \param handle is a non-zero pointer to an embedded SPE image.
59  *
60  * If successful returns a boost::shared_ptr that does nothing when
61  * it's time to free the object.
62  *
63  * \sa gc_program_handle_from_filename
64  */
65 spe_program_handle_sptr 
66 gc_program_handle_from_address(spe_program_handle_t *handle);
67
68 /*!
69  * \brief map gc_job_status_t into a string
70  */
71 const std::string
72 gc_job_status_string(gc_job_status_t status);
73
74 /*
75  * \brief Options that configure the job_manager.
76  * The default values are reasonable.
77  */
78 struct gc_jm_options {
79   unsigned int max_jobs;            // max # of job descriptors in system
80   unsigned int max_client_threads;  // max # of client threads of job manager
81   unsigned int nspes;               // how many SPEs shall we use? 0 -> all of them
82   bool gang_schedule;               // shall we gang schedule?
83   bool use_affinity;                // shall we try for affinity (FIXME not implmented)
84   bool enable_logging;              // shall we log SPE events?
85   uint32_t log2_nlog_entries;              // log2 of number of log entries (default is 12 == 4k)
86   spe_program_handle_sptr program_handle;  // program to load into SPEs
87
88   gc_jm_options() :
89     max_jobs(0), max_client_threads(0), nspes(0),
90     gang_schedule(false), use_affinity(false),
91     enable_logging(false), log2_nlog_entries(12)
92   {
93   }
94
95   gc_jm_options(spe_program_handle_sptr program_handle_,
96                 unsigned int nspes_ = 0) :
97     max_jobs(0), max_client_threads(0), nspes(nspes_),
98     gang_schedule(false), use_affinity(false),
99     enable_logging(false), log2_nlog_entries(12),
100     program_handle(program_handle_)
101   {
102   }
103 };
104
105 enum gc_wait_mode {
106   GC_WAIT_ANY,
107   GC_WAIT_ALL,
108 };
109
110 /*
111  * exception classes
112  */
113 class gc_exception : public std::runtime_error
114 {
115 public:
116   gc_exception(const std::string &msg);
117 };
118
119 class gc_unknown_proc : public gc_exception
120 {
121 public:
122   gc_unknown_proc(const std::string &msg);
123 };
124
125 class gc_bad_alloc : public gc_exception
126 {
127 public:
128   gc_bad_alloc(const std::string &msg);
129 };
130
131 class gc_bad_align : public gc_exception
132 {
133 public:
134   gc_bad_align(const std::string &msg);
135 };
136
137 class gc_bad_submit : public gc_exception
138 {
139 public:
140   gc_bad_submit(const std::string &name, gc_job_status_t status);
141 };
142
143 /*
144  * \brief Create an instance of the job manager
145  */
146 gc_job_manager_sptr
147 gc_make_job_manager(const gc_jm_options *options = 0);
148
149
150 /*!
151  * \brief Abstract class that manages SPE jobs.
152  * \ingroup gcell
153  *
154  * There is typically a single instance derived from this class.
155  * It is safe to call its methods from any thread.
156  */
157 class gc_job_manager : boost::noncopyable
158 {
159 public:
160   gc_job_manager(const gc_jm_options *options = 0); 
161
162   virtual ~gc_job_manager();
163
164   /*!
165    * Stop accepting new jobs.  Wait for existing jobs to complete.
166    * Return all managed SPE's to the system.
167    */
168   virtual bool shutdown() = 0;
169
170   /*!
171    * \brief Return number of SPE's currently allocated to job manager.
172    */
173   virtual int nspes() const = 0;
174
175   /*!
176    * \brief Return a pointer to a properly aligned job descriptor,
177    * or throws gc_bad_alloc if there are none available.
178    */
179   virtual gc_job_desc *alloc_job_desc() = 0;
180
181   /*
182    *! Free a job descriptor previously allocated with alloc_job_desc()
183    *
184    * \param[in] jd pointer to job descriptor to free.
185    */
186   virtual void free_job_desc(gc_job_desc *jd) = 0;
187
188   /*!
189    * \brief Submit a job for asynchronous processing on an SPE.
190    *
191    * \param[in] jd pointer to job description
192    *
193    * The caller must not read or write the job description
194    * or any of the memory associated with any indirect arguments
195    * until after calling wait_job.
196    *
197    * \returns true iff the job was successfully enqueued.
198    * If submit_job returns false, check jd->status for additional info.
199    */
200   virtual bool submit_job(gc_job_desc *jd) = 0;
201
202   /*!
203    * \brief Wait for job to complete.
204    *
205    * A thread may only wait for jobs which it submitted.
206    *
207    * \returns true if sucessful, else false.
208    */
209   virtual bool 
210   wait_job(gc_job_desc *jd) = 0;
211
212   /*!
213    * \brief wait for 1 or more jobs to complete.
214    *
215    * \param[in] njobs is the length of arrays \p jd and \p done.
216    * \param[in] jd are the jobs that are to be waited for.
217    * \param[out] done indicates whether the corresponding job is complete.
218    * \param[in] mode indicates whether to wait for ALL or ANY of the jobs
219    *   in \p jd to complete.
220    *
221    * A thread may only wait for jobs which it submitted.
222    *
223    * \returns number of jobs completed, or -1 if error.
224    * The caller must examine the status field of each job to confirm
225    * successful completion of the job.
226    */
227   virtual int
228   wait_jobs(unsigned int njobs,
229             gc_job_desc *jd[], bool done[], gc_wait_mode mode) = 0;
230
231   /*!
232    * Return the maximum number of bytes of EA arguments that may be
233    * copied to or from the SPE in a single job.  The limit applies
234    * independently to the "get" and "put" args.  
235    * \sa gc_job_desc_t, gc_job_ea_args_t
236    */
237   virtual int ea_args_maxsize() = 0;
238
239   /*!
240    * Return gc_proc_id_t associated with spu procedure \p proc_name if one
241    * exists, otherwise throws gc_unknown_proc.
242    */
243   virtual gc_proc_id_t lookup_proc(const std::string &proc_name) = 0;
244   
245   /*!
246    * Return a vector of all known spu procedure names.
247    */
248   virtual std::vector<std::string> proc_names() = 0;
249
250   virtual void set_debug(int debug);
251   virtual int debug();
252
253   /* ----- static methods ----- */
254
255   /*!
256    * \brief Set the singleton gc_job_manager instance.
257    * \param mgr is the job manager instance.
258    *
259    * The singleton is weakly held, thus the caller must maintain
260    * a reference to the mgr for the duration.  (If we held the
261    * manager strongly, the destructor would never be called, and the
262    * resources (SPEs) would not be returned.)  Bottom line: the
263    * caller is responsible for life-time management.
264    */
265   static void set_singleton(gc_job_manager_sptr mgr);
266
267   /*!
268    * \brief Retrieve the singleton gc_job_manager instance.
269    *
270    * Returns the singleton gc_job_manager instance or raises
271    * boost::bad_weak_ptr if the singleton is empty.
272    */
273   static gc_job_manager_sptr singleton();
274
275   /*!
276    * \brief return a boost::shared_ptr to a job descriptor.
277    */
278   static gc_job_desc_sptr make_jd_sptr(gc_job_manager_sptr mgr, gc_job_desc *jd);
279
280   /*!
281    * \brief allocate a job descriptor and return a boost::shared_ptr to it.
282    */
283   static gc_job_desc_sptr alloc_job_desc(gc_job_manager_sptr mgr);
284 };
285
286
287 #endif /* INCLUDED_GC_JOB_MANAGER_H */