Main Page | Class Hierarchy | Compound List | File List | Compound Members | File Members

cosyselect.cc

Go to the documentation of this file.
00001 /*--------------------------------------------------------------------
00002  *
00003  * (C) Copyright Koninklijke Philips Electronics NV 2006. 
00004  * All rights reserved. This software is licensed under the terms of
00005  * version 2.1 of the GNU Lesser General Public License as published 
00006  * by the Free Software Foundation. For licensing and warranty
00007  * information, see the file COPYING in the main directory.
00008  *
00009  *------------------------------------------------------------------*/
00010 
00011 #include <sys/types.h>
00012 #include "cosyselect.h"
00013 #include "rte.h"
00014 #include "cosyfifo.h"
00015 #include "portimpl.h"
00016 #include "fifoimpl.h"
00017 #include "semaphoreapi.h"
00018 #include "utilbase.h"
00019 
00020 #include <stdlib.h>
00021 
00022 bool cosySelect::random = true;
00023 
00024 unsigned int rnd(unsigned int n)
00025 {
00026   return rand() % n;
00027 }
00028 
00029 cosySelect::cosySelect(SelectImpl& s, cosyRte& r) : 
00030   rteSelect(s), retvalue(0), sema(0), block(false)
00031 { 
00032   rte = &r;
00033 }
00034 
00035 cosySelect::~cosySelect()
00036 { }
00037 
00038 void cosySelect::pushBack(const InPortImpl& p, unsigned int n)
00039 {
00040   f.push_back ((cosyFifo*)((FifoImpl*)getFarFifo(&p))->rte());
00041   s.push_back (n);
00042   input.push_back (true);
00043   r.push_back (retvalue);
00044   retvalue++;
00045 }
00046 
00047 void cosySelect::pushBack(const OutPortImpl& p, unsigned int n)
00048 {
00049   FifoImpl* fifo = (FifoImpl*)getFarFifo(&p);
00050   for (unsigned int i=0; i<fifo->nrRteFifos(); i++)
00051   {
00052     f.push_back ((cosyFifo*)fifo->rte(i));
00053     s.push_back (n);
00054     input.push_back (false);
00055     r.push_back (retvalue);
00056   }
00057   retvalue++;
00058 }
00059 
00060 unsigned int cosySelect::select()
00061 {
00062   if (f.size() == 0) {
00063     rte->cerr() << "Error: There are no ports added" <<
00064       " to the selectList '" << base->name() << "'" << std::endl;
00065     exit (1);
00066   }
00067 
00068   std::vector<int> enable(f.size());  // index of enabled fifos
00069   int enabled = 0;
00070   unsigned int i;
00071 
00072 #ifdef PREEMPTIVE
00073   // lock all fifos, such that they cannot be updated while 
00074   // selector is busy
00075   for (i = 0; i < f.size(); i++)
00076     f[i]->lock();
00077 #endif
00078 
00079   for (i = 0; i < f.size(); i++)
00080   {
00081     if (input[i]) {
00082       if (s[i] <= f[i]->wn + f[i]->data())
00083       {
00084         enable[enabled++] = i;
00085       }
00086     } else {
00087       if (s[i] <= f[i]->rn - f[i]->data())
00088       {
00089         enable[enabled++] = i;
00090       }
00091     }
00092   }
00093 
00094   if (!enabled) {
00095 
00096     // none of the fifos is enabled: block
00097 
00098     for (i=0; i < f.size(); i++)
00099     {
00100       if (!f[i]->sel) {
00101         f[i]->sel = this;
00102       } else {
00103         printf("Error: multiple select operations are active simultaneously on channel %s\n",f[i]->api()->fullName());
00104         exit(1);
00105       }
00106   
00107       if (input[i]) {
00108         // ws is set to the number of items that
00109         // has to be written
00110         f[i]->ws = s[i] - f[i]->data();
00111       } else {
00112         // rs is set to the number of items that
00113         // has to be read
00114         f[i]->rs = s[i] + f[i]->data();
00115       }
00116     }
00117     
00118     block = true;
00119 
00120 #ifdef PREEMPTIVE
00121     for (i = 0; i < f.size(); i++)
00122       f[i]->unlock();
00123 #endif
00124 
00125     sema.wait();
00126     // returns here after one or more Selector::signal()
00127 
00128 #ifdef PREEMPTIVE
00129     for (i=0; i < f.size(); i++)
00130       f[i]->lock();
00131 #endif
00132 
00133     for (i=0; i < f.size(); i++)
00134     {
00135       if (f[i]->sel) {
00136         f[i]->sel = 0;
00137       } else {
00138         enable[enabled++] = i;
00139       }
00140     }
00141   }
00142 
00143 #ifdef PREEMPTIVE
00144   for (i = 0; i < f.size(); i++)
00145     f[i]->unlock();
00146 #endif
00147 
00148   return r[enable[random ? rnd(enabled) : 0]];
00149 }
00150 
00151 void cosySelect::signal()
00152 {
00153   // can be called multiple times
00154 
00155 #ifdef PREEMPTIVE
00156   lock();
00157 #endif
00158   if (block) {
00159     block = false;
00160     sema.signal();
00161   }
00162 #ifdef PREEMPTIVE
00163   unlock();
00164 #endif
00165 }
00166 
00167 #ifdef PREEMPTIVE
00168 void cosySelect::lock()
00169 {
00170   mutex.lock();
00171 }
00172 
00173 void cosySelect::unlock()
00174 {
00175   mutex.unlock();
00176 }
00177 #endif
00178 

Generated on Wed Feb 15 14:52:38 2006 for yapi by doxygen 1.3.2