|
1 // Copyright (c) 1998-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". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // e32test\misc\t_asid.cpp |
|
15 // |
|
16 // |
|
17 #define __E32TEST_EXTENSION__ |
|
18 #include <e32test.h> |
|
19 #include <e32svr.h> |
|
20 #include <u32std.h> |
|
21 |
|
22 #include "t_asid.h" |
|
23 #include "d_asid.h" |
|
24 |
|
25 #define TEST_R(r, e) if (!(e)) {RDebug::Printf("Failure at line %d, r = %d", __LINE__, r); return r; } |
|
26 |
|
27 _LIT(KDummyProcessName,"T_ASID_DUMMY"); |
|
28 |
|
29 RTest test(_L("T_ASID")); |
|
30 |
|
31 const TUint KMaxAsids = 256; // On arm and current version of FMM has maximum of 256 active processes at once. |
|
32 const TUint KLeakedProcesses = KMaxAsids<<1; |
|
33 |
|
34 void TestMaxAsids() |
|
35 { |
|
36 test.Printf(_L("Attempt to load > %d zombie processes\n"), KMaxAsids); |
|
37 RProcess* processes = new RProcess[KLeakedProcesses]; |
|
38 TUint i = 0; |
|
39 for (; i < KLeakedProcesses; i++) |
|
40 { |
|
41 test_KErrNone(processes[i].Create(KDummyProcessName, KNullDesC)); |
|
42 TRequestStatus s; |
|
43 processes[i].Logon(s); |
|
44 test_Equal(KRequestPending, s.Int()); |
|
45 processes[i].Resume(); |
|
46 User::WaitForRequest(s); |
|
47 if (processes[i].ExitType()!=EExitKill || processes[i].ExitReason()!=KErrNone) |
|
48 { |
|
49 TExitCategoryName aExitCategory = processes[i].ExitCategory(); |
|
50 test.Printf(_L("Exit %d,%d,%S\n"),processes[i].ExitType(),processes[i].ExitReason(),&aExitCategory); |
|
51 test(0); |
|
52 } |
|
53 } |
|
54 // Clean up the process handles here. |
|
55 for (i = 0; i < KLeakedProcesses; i++) |
|
56 processes[i].Close(); |
|
57 delete[] processes; |
|
58 } |
|
59 |
|
60 |
|
61 TInt TestIpcThread(TAny*) |
|
62 { |
|
63 // Start a server for zombie to connect to. |
|
64 RServer2 ipcServer; |
|
65 TInt r = ipcServer.CreateGlobal(KAsidIpcServerName); |
|
66 TEST_R(r, r == KErrNone); |
|
67 RMessage2 ipcMessage; |
|
68 for (TUint i = 0; i < 300; i++) |
|
69 { |
|
70 // Start the process. |
|
71 RProcess zombie; |
|
72 TInt r = zombie.Create(KDummyProcessName, KAsidIpcServerName); |
|
73 TEST_R(r, r == KErrNone); |
|
74 TRequestStatus s; |
|
75 zombie.Logon(s); |
|
76 TEST_R(s.Int(), s.Int() == KRequestPending); |
|
77 zombie.Resume(); |
|
78 |
|
79 // Wait for the connect and ipc message from the zombie |
|
80 ipcServer.Receive(ipcMessage); |
|
81 TEST_R(ipcMessage.Function(), ipcMessage.Function() == EConnect); |
|
82 ipcMessage.Complete(KErrNone); |
|
83 ipcServer.Receive(ipcMessage); |
|
84 TEST_R(ipcMessage.Function(), ipcMessage.Function() == EIpcData); |
|
85 |
|
86 TUint8 array1[KAsidDesLen]; |
|
87 memset(array1, KAsidValue, KAsidDesLen); |
|
88 TPtr8 buf1(array1, KAsidDesLen, KAsidDesLen); |
|
89 |
|
90 TUint8 array[KAsidDesLen]; |
|
91 TPtr8 buf(array, KAsidDesLen); |
|
92 test_Equal(KErrNone, ipcMessage.Read(0, buf)); |
|
93 r = ipcMessage.Read(0, buf); |
|
94 TEST_R(r, r == KErrNone); |
|
95 r = buf.Compare(buf1); |
|
96 TEST_R(r, r == 0); |
|
97 ipcMessage.Complete(KErrNone); |
|
98 |
|
99 // Try to read from the client while it is exiting. |
|
100 ipcServer.Receive(ipcMessage); |
|
101 TEST_R(ipcMessage.Function(), ipcMessage.Function() == EIpcData); |
|
102 User::After(5*i); |
|
103 |
|
104 r = ipcMessage.Read(0, buf); |
|
105 //RDebug::Printf("%d", r); |
|
106 |
|
107 // Wait for client to exit. |
|
108 User::WaitForRequest(s); |
|
109 TEST_R(s.Int(), s.Int() == KErrNone); |
|
110 ipcServer.Receive(ipcMessage); // Clear out the disconnect message. |
|
111 TEST_R(ipcMessage.Function(), ipcMessage.Function() == EDisConnect); |
|
112 ipcMessage.Complete(KErrNone); |
|
113 zombie.Close(); |
|
114 } |
|
115 ipcServer.Close(); |
|
116 return KErrNone; |
|
117 } |
|
118 |
|
119 |
|
120 TInt TestDesThread(TAny*) |
|
121 { |
|
122 RAsidLdd asidLdd; |
|
123 TInt r = asidLdd.Open(); |
|
124 TEST_R(r, r == KErrNone); |
|
125 RMessage2 desMessage; |
|
126 RServer2 desServer; |
|
127 // Start a server for zombie to connect to. |
|
128 r = desServer.CreateGlobal(KAsidDesServerName); |
|
129 TEST_R(r, r == KErrNone); |
|
130 |
|
131 for (TUint i = 0; i < 300; i++) |
|
132 { |
|
133 // Start the process. |
|
134 RProcess zombie; |
|
135 r = zombie.Create(KDummyProcessName, KAsidDesServerName); |
|
136 TEST_R(r, r == KErrNone); |
|
137 TRequestStatus s; |
|
138 zombie.Logon(s); |
|
139 TEST_R(s.Int(), s.Int() == KRequestPending); |
|
140 zombie.Resume(); |
|
141 |
|
142 // Wait for the connect and des message from the zombie |
|
143 desServer.Receive(desMessage); |
|
144 TEST_R(desMessage.Function(), desMessage.Function() == EConnect); |
|
145 desMessage.Complete(KErrNone); |
|
146 desServer.Receive(desMessage); |
|
147 TEST_R(desMessage.Function(), desMessage.Function() == EDesData); |
|
148 |
|
149 TAny* desPtr = (TAny*)desMessage.Ptr0(); |
|
150 TAny* threadPtr = (TAny*)desMessage.Ptr1(); |
|
151 // Open a handle on the client's thread to stop it being deleted. |
|
152 r = asidLdd.OpenThread(threadPtr); |
|
153 TEST_R(r, r == KErrNone); |
|
154 SDesHeader desHdr; |
|
155 desHdr.iDes = desPtr; |
|
156 r = asidLdd.ReadDesHeader(threadPtr, desHdr); |
|
157 TEST_R(r, r == KErrNone); |
|
158 TEST_R(desHdr.iLength, desHdr.iLength == KAsidDesLen); |
|
159 TEST_R(desHdr.iMaxLength, desHdr.iMaxLength == KAsidDesLen); |
|
160 desMessage.Complete(KErrNone); |
|
161 |
|
162 // Wait for further des message from client. |
|
163 desServer.Receive(desMessage); |
|
164 TEST_R(desMessage.Function(), desMessage.Function() == EDesData); |
|
165 desPtr = (TAny*)desMessage.Ptr0(); |
|
166 TEST_R((TInt)desMessage.Ptr1(), (TInt)desMessage.Ptr1() == (TInt)threadPtr); |
|
167 |
|
168 // Try to read descriptor header from the client while it is exiting. |
|
169 TInt r = asidLdd.ReadDesHeader(threadPtr, desHdr); |
|
170 User::After(5*i); |
|
171 |
|
172 //RDebug::Printf("%d", r); |
|
173 if (r == KErrNone) |
|
174 { |
|
175 TEST_R(desHdr.iLength, desHdr.iLength == KAsidDesLen); |
|
176 TEST_R(desHdr.iMaxLength, desHdr.iMaxLength == KAsidDesLen); |
|
177 } |
|
178 |
|
179 // Wait for client to exit. |
|
180 User::WaitForRequest(s); |
|
181 TEST_R(s.Int(), s.Int() == KErrNone); |
|
182 desServer.Receive(desMessage); // Clear out the disconnect message. |
|
183 TEST_R(desMessage.Function(), desMessage.Function() == EDisConnect); |
|
184 desMessage.Complete(KErrNone); |
|
185 // Close handles in client process and thread. |
|
186 r = asidLdd.CloseThread(); |
|
187 TEST_R(r, r == KErrNone); |
|
188 zombie.Close(); |
|
189 } |
|
190 desServer.Close(); |
|
191 asidLdd.Close(); |
|
192 return KErrNone; |
|
193 } |
|
194 |
|
195 GLDEF_C TInt E32Main() |
|
196 { |
|
197 test.Title(); |
|
198 test.Start(_L("Test zombie processes release their ASIDs")); |
|
199 |
|
200 // Get memory model. |
|
201 if ((UserSvr::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, NULL, NULL)&EMemModelTypeMask) < EMemModelTypeFlexible) |
|
202 { |
|
203 test.Printf(_L("SKIPPING TEST - Older memory models don't release ASIDs from zombie processes\n")); |
|
204 test.End(); |
|
205 return KErrNone; |
|
206 } |
|
207 |
|
208 TestMaxAsids(); |
|
209 |
|
210 test.Next(_L("Test ipc message copy to a zombie process")); |
|
211 |
|
212 test_KErrNone(TestIpcThread(NULL)); |
|
213 TestMaxAsids(); |
|
214 |
|
215 test.Next(_L("Test reading descriptor header from a zombie process")); |
|
216 test_KErrNone(TestDesThread(NULL)); |
|
217 TestMaxAsids(); |
|
218 |
|
219 test.Next(_L("Test ipc and des header to zombie processes concurrently")); |
|
220 RThread ipcThread; |
|
221 RThread desThread; |
|
222 ipcThread.Create(KNullDesC, TestIpcThread, 0x2000, NULL, NULL); |
|
223 desThread.Create(KNullDesC, TestDesThread, 0x2000, NULL, NULL); |
|
224 TRequestStatus ipcStatus; |
|
225 TRequestStatus desStatus; |
|
226 ipcThread.Logon(ipcStatus); |
|
227 desThread.Logon(desStatus); |
|
228 ipcThread.Resume(); |
|
229 desThread.Resume(); |
|
230 |
|
231 // Wait for threads to complete. |
|
232 User::WaitForRequest(ipcStatus); |
|
233 test_KErrNone(ipcStatus.Int()); |
|
234 User::WaitForRequest(desStatus); |
|
235 test_KErrNone(desStatus.Int()); |
|
236 TestMaxAsids(); |
|
237 |
|
238 test.End(); |
|
239 return KErrNone; |
|
240 } |