00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <sys/types.h>
00012 #include "cosyfifo.h"
00013 #include "rte.h"
00014 #include "cosyselect.h"
00015 #include "fifoimpl.h"
00016 #include "taskapi.h"
00017 #include <limits.h>
00018 #include <minmax.h>
00019
00020 #include "cosyprocess.h"
00021 #include "utilbase.h"
00022
00023 unsigned int cosyFifo::defaultMinSize = 1;
00024 unsigned int cosyFifo::defaultMaxSize = 2*1024;
00025 unsigned int cosyFifo::defaultBytes = 512;
00026
00027 unsigned int cosyFifo::calcSize(unsigned int lo, unsigned int hi, unsigned int s)
00028 {
00029 if (lo > hi) {
00030 rte->cerr() << "Sorry, cannot implement Fifo size" << std::endl;
00031 exit(1);
00032 }
00033
00034
00035 return min(max(lo, s), hi);
00036 }
00037
00038 cosyFifo::cosyFifo(FifoImpl& f, cosyRte& r) :
00039 rteFifo(f),
00040 rte(&r),
00041 minSize(max(f.minSize(), defaultMinSize)),
00042 maxSize(f.maxSize() == INT_MAX ? defaultMaxSize : f.maxSize()),
00043 countw(0), countr(0), wcount(0), rcount(0),
00044 q(calcSize(minSize,maxSize,defaultBytes/f.tokenSize()),f.tokenSize()),
00045 wp(0), rp(0), wn(0), rn(0), ws(0), rs(0),
00046 block(false), sema(0), sel(0)
00047 { }
00048
00049 unsigned int cosyFifo::size() const
00050 {
00051 return q.size();
00052 }
00053
00054 unsigned int cosyFifo::data() const
00055 {
00056 return q.data();
00057 }
00058
00059 unsigned int cosyFifo::room() const
00060 {
00061 return q.room();
00062 }
00063
00064 #ifdef PREEMPTIVE
00065 void cosyFifo::lock()
00066 {
00067 mutex.lock();
00068 }
00069
00070 void cosyFifo::unlock()
00071 {
00072 mutex.unlock();
00073 }
00074 #endif
00075
00076 void cosyFifo::read(void* p, unsigned int nitems)
00077 {
00078 #ifdef PREEMPTIVE
00079 lock();
00080 #endif
00081
00082 rp = (char*)p;
00083 rn = nitems;
00084
00085 if (sel) {
00086 if (rs <= rn) {
00087 sel->signal();
00088 sel = 0;
00089 } else {
00090 rs -= rn;
00091 }
00092 }
00093
00094 while (rn) {
00095 if (rn <= q.data()) {
00096 q.get(rp, rn);
00097 countr += rn;
00098 rn = 0;
00099 if (block && (wn <= q.room())) {
00100 block = false;
00101 sema.signal();
00102 }
00103 } else {
00104 if (block) {
00105 unsigned int d = q.data();
00106 q.get(rp, d);
00107 countr += d;
00108 rp += d*api()->tokenSize();
00109 rn -= d;
00110
00111 sema.signal();
00112 }
00113
00114 block = true;
00115 #ifdef PREEMPTIVE
00116 unlock();
00117 #endif
00118 sema.wait();
00119 #ifdef PREEMPTIVE
00120 lock();
00121 #endif
00122 }
00123 }
00124
00125
00126 rcount++;
00127
00128 #ifdef PREEMPTIVE
00129 unlock();
00130 #endif
00131 }
00132
00133 void cosyFifo::write(const void* p, unsigned int nitems)
00134 {
00135 #ifdef PREEMPTIVE
00136 lock();
00137 #endif
00138
00139 wp = (char*)p;
00140 wn = nitems;
00141
00142 if (sel) {
00143 if (ws <= wn) {
00144 sel->signal();
00145 sel = 0;
00146 } else {
00147 ws -= wn;
00148 }
00149 }
00150
00151 while (wn) {
00152 if (wn <= q.room()) {
00153 q.put(wp, wn);
00154 countw += wn;
00155 wn = 0;
00156 if (block && (rn <= q.data())) {
00157 block = false;
00158 sema.signal();
00159 }
00160 } else {
00161 if (block) {
00162 unsigned int r = q.room();
00163 q.put(wp, r);
00164 countw += r;
00165 wp += r*api()->tokenSize();
00166 wn -= r;
00167
00168 sema.signal();
00169 }
00170
00171 block = true;
00172 #ifdef PREEMPTIVE
00173 unlock();
00174 #endif
00175 sema.wait();
00176 #ifdef PREEMPTIVE
00177 lock();
00178 #endif
00179 }
00180 }
00181
00182
00183 wcount++;
00184
00185 #ifdef PREEMPTIVE
00186 unlock();
00187 #endif
00188 }
00189
00190 bool cosyFifo::grow()
00191 {
00192 if (block && (0 < wn) && (q.data() + wn <= maxSize))
00193 {
00194 #ifdef PREEMPTIVE
00195 lock();
00196 #endif
00197 unsigned int sz = q.data() + wn;
00198 q.resize(sz);
00199 q.put(wp, wn);
00200 countw += wn;
00201 wn = 0;
00202 block = false;
00203 sema.signal();
00204 #ifdef PREEMPTIVE
00205 unlock();
00206 #endif
00207 return true;
00208 }
00209 return false;
00210 }
00211
00212 const char* cosyFifo::getMetricName(FifoMetric m)
00213 {
00214 switch (m) {
00215 case MinSize: return "min";
00216 case MaxSize: return "max";
00217 case Size: return "size";
00218 case Data: return "data";
00219 case Room: return "room";
00220 case TokensWritten: return "Wtokens";
00221 case TokensRead: return "Rtokens";
00222 case PendingWriteTokens:return "Wpend";
00223 case PendingReadTokens: return "Rpend";
00224 case NeededWriteTokens: return "Wneed";
00225 case NeededReadTokens: return "Rneed";
00226 case WriteCalls: return "Wcalls";
00227 case ReadCalls: return "Rcalls";
00228 case TokensPerWrite: return "T/W";
00229 case TokensPerRead: return "T/R";
00230 case TokenSize: return "Tsize";
00231 case BytesWritten: return "Wbytes";
00232 case BytesRead: return "Rbytes";
00233 default: return "unknown fifo metric";
00234 }
00235 }
00236
00237 unsigned int cosyFifo::getMetricValue(FifoMetric m)
00238 {
00239 switch (m) {
00240 case MinSize: return minSize;
00241 case MaxSize: return maxSize;
00242 case Size: return size();
00243 case Data: return data();
00244 case Room: return room();
00245 case TokensRead: return countr;
00246 case TokensWritten: return countw;
00247 case PendingWriteTokens:return wn;
00248 case PendingReadTokens: return rn;
00249 case NeededWriteTokens: return ws;
00250 case NeededReadTokens: return rs;
00251 case WriteCalls: return wcount;
00252 case ReadCalls: return rcount;
00253 case TokensPerWrite: return (wcount == 0) ? 0
00254 : countw / wcount;
00255 case TokensPerRead: return (rcount == 0) ? 0
00256 : countr / rcount;
00257 case TokenSize: return api()->tokenSize();
00258 case BytesWritten: return countw * api()->tokenSize();
00259 case BytesRead: return countr * api()->tokenSize();
00260 default: return 0;
00261 }
00262 }