Update contrib.
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32test\nkernsa\fastbuf.cpp
18 #include <nktest/nkutils.h>
24 static WaitFreePipe<T>* New(TInt aSize);
29 TInt Write(const T& aIn);
30 inline TUint32 Waits() {return iWaits;}
31 inline void ResetWaits() {iWaits = 0;}
39 NRequestStatus* volatile iStat;
41 volatile TUint32 iWaits;
45 WaitFreePipe<T>::WaitFreePipe()
53 WaitFreePipe<T>::~WaitFreePipe()
59 WaitFreePipe<T>* WaitFreePipe<T>::New(TInt aSize)
61 WaitFreePipe<T>* p = new WaitFreePipe<T>;
64 p->iBase = (T*)malloc(aSize * sizeof(T));
70 p->iEnd = p->iBase + aSize;
77 void WaitFreePipe<T>::InitWriter()
82 void WaitFreePipe<T>::InitReader()
84 iReader = NKern::CurrentThread();
88 void WaitFreePipe<T>::Read(T& aOut)
90 while (iRead == iWrite)
94 // make sure set to KRequestPending is seen before iStat write
95 __e32_atomic_store_ord_ptr(&iStat, &s);
96 // make sure writer sees our request status before we check for buffer empty again
98 RequestComplete(iReader, (NRequestStatus*&)iStat, 0);
103 T* new_read = iRead + 1;
104 if (new_read == iEnd)
106 // make sure read of data value is observed before update of read pointer
107 __e32_atomic_store_rel_ptr(&iRead, new_read);
111 TInt WaitFreePipe<T>::Write(const T& aIn)
113 T* new_write = iWrite + 1;
114 if (new_write == iEnd)
116 if (new_write == iRead)
117 return KErrOverflow; // buffer full
119 // make sure data is seen before updated write pointer
120 __e32_atomic_store_ord_ptr(&iWrite, new_write);
122 RequestComplete(iReader, (NRequestStatus*&)iStat, 0);
129 WaitFreePipe<TUint32>* iPipe;
130 TUint64 iTotalWrites;
132 volatile TUint32 iWrites;
133 volatile TUint32 iReads;
135 volatile TUint32 iReadTime;
136 volatile TUint32 iWriteTime;
137 volatile TBool iStop;
140 void PipeWriterThread(TAny* aPtr)
142 SPipeTest& a = *(SPipeTest*)aPtr;
143 a.iPipe->InitWriter();
144 TUint32 seed[2] = {1,0};
145 TUint32 seqs[2] = {3,0};
149 TUint32 x = random(seqs);
151 r = a.iPipe->Write(x);
153 fcfspin(2*a.iWriteTime);
154 } while (r != KErrNone);
157 while (a.iWrites>=a.iMeasure)
159 TUint32 time = random(seed) % a.iWriteTime;
164 void PipeReaderThread(TAny* aPtr)
166 SPipeTest& a = *(SPipeTest*)aPtr;
167 TUint32 seed[2] = {2,0};
168 TUint32 seqs[2] = {3,0};
169 a.iPipe->InitReader();
170 a.iPipe->ResetWaits();
173 TUint32 x = random(seqs);
176 TEST_RESULT(x==y, "Wrong value");
179 if (a.iReads < a.iMeasure)
181 TUint32 time = random(seed) % a.iReadTime;
185 TUint32 w = a.iPipe->Waits();
186 TUint32 wr = (w<<4)/a.iMeasure;
187 TEST_PRINT3("%d waits out of %d (wr=%d)", w, a.iMeasure, wr);
188 TUint32 rt = a.iReadTime;
189 TUint32 wt = a.iWriteTime;
194 a.iWriteTime = wt<<1;
199 a.iReadTime = rt - (rt>>2);
200 a.iWriteTime = wt + (wt>>2);
205 a.iReadTime = rt - (rt>>3);
206 a.iWriteTime = wt + (wt>>3);
215 a.iReadTime = rt - (rt>>3);
216 a.iWriteTime = wt + (wt>>3);
221 a.iReadTime = rt + (rt>>2);
222 a.iWriteTime = wt - (wt>>2);
227 a.iWriteTime = wt>>1;
230 TEST_PRINT4("RT: %d->%d WT: %d->%d", rt, a.iReadTime, wt, a.iWriteTime);
231 a.iPipe->ResetWaits();
240 memclr(&a, sizeof(a));
241 a.iPipe = WaitFreePipe<TUint32>::New(1024);
247 NFastSemaphore exitSem(0);
248 NThread* reader = CreateThreadSignalOnExit("Reader", &PipeReaderThread, 11, &a, 0, -1, &exitSem, 0);
250 NThread* writer = CreateThreadSignalOnExit("Writer", &PipeWriterThread, 11, &a, 0, -1, &exitSem, 1);
253 while (a.iTotalWrites < 0x01000000u)
257 NKern::FSWait(&exitSem);
258 NKern::FSWait(&exitSem);
261 void TestWaitFreePipe()