00001
00002
00003
00004
00005
00006
00007
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());
00069 int enabled = 0;
00070 unsigned int i;
00071
00072 #ifdef PREEMPTIVE
00073
00074
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
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
00109
00110 f[i]->ws = s[i] - f[i]->data();
00111 } else {
00112
00113
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
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
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