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

cosyfifo.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 "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; // should be 0 !
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   // choose defaultSize depending on default/token size (bytes)
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();   // enter critical section
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(); // leave critical section
00117 #endif
00118       sema.wait();
00119 #ifdef PREEMPTIVE
00120       lock();   // enter critical section
00121 #endif
00122     }
00123   }
00124   
00125   // statistics
00126   rcount++;
00127 
00128 #ifdef PREEMPTIVE
00129   unlock(); // leave critical section
00130 #endif
00131 }
00132 
00133 void cosyFifo::write(const void* p, unsigned int nitems)
00134 {
00135 #ifdef PREEMPTIVE
00136   lock();   // enter critical section
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(); // leave critical section
00174 #endif
00175       sema.wait();
00176 #ifdef PREEMPTIVE
00177       lock();   // enter critical section
00178 #endif
00179     }
00180   }
00181 
00182   // statistics
00183   wcount++;
00184 
00185 #ifdef PREEMPTIVE
00186   unlock(); // leave critical section
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 }

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