|
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 "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 // C routines for creating EPOC32 threads |
|
15 // |
|
16 // |
|
17 |
|
18 #include <e32std.h> |
|
19 #include <estlib.h> /* for SpawnPosixServerThread */ |
|
20 #include <unistd.h> |
|
21 #include <stdio.h> /* for popen3 */ |
|
22 #include <stdlib.h> /* for mbstowcs */ |
|
23 #include "CTEST.H" |
|
24 #include <sys/errno.h> /* for errno */ |
|
25 #include <sys/wait.h> |
|
26 |
|
27 typedef void (*FUNC)(); |
|
28 |
|
29 struct cthread |
|
30 { |
|
31 RThread iThread; |
|
32 RProcess iProcess; |
|
33 TRequestStatus iStatus; |
|
34 int pid; |
|
35 }; |
|
36 |
|
37 TInt threadhelper (TAny* aFn) |
|
38 { |
|
39 CTrapCleanup::New(); |
|
40 FUNC f=(FUNC)aFn; |
|
41 (*f)(); |
|
42 return 0; |
|
43 } |
|
44 |
|
45 #if defined(__WINS__) |
|
46 |
|
47 IMPORT_C void NewProcessId(); // WINS bodges for multiple "processes" |
|
48 IMPORT_C void NextProcessFn(TAny*); |
|
49 |
|
50 TInt processhelper (TAny* aFn) |
|
51 { |
|
52 // Do the MCRT0.OBJ things straight away |
|
53 NewProcessId(); |
|
54 SpawnPosixServerThread(); |
|
55 char wd[80]; |
|
56 getcwd(wd, sizeof(wd)); // connect to CPosixServer |
|
57 return threadhelper(aFn); |
|
58 } |
|
59 |
|
60 #endif //__WINS__ |
|
61 |
|
62 |
|
63 extern "C" { |
|
64 |
|
65 EXPORT_C int start_posix_server() |
|
66 { |
|
67 start_redirection_server(); |
|
68 return SpawnPosixServerThread(); |
|
69 } |
|
70 |
|
71 EXPORT_C void* create_thread(void (*aFn)(), char* aName) |
|
72 { |
|
73 #ifdef _UNICODE |
|
74 TPtrC8 ptr((TText8*)aName); |
|
75 TBuf<80> name; |
|
76 name.Copy(ptr); |
|
77 #else |
|
78 TPtrC8 name((TText8*)aName); |
|
79 #endif /* _UNICODE */ |
|
80 struct cthread* t = new cthread; |
|
81 // 16k stack, share parent's heap |
|
82 TInt err=t->iThread.Create(name, threadhelper, 0x4000, NULL, (TAny*)aFn); |
|
83 t->iThread.Logon(t->iStatus); |
|
84 if (err!= KErrNone) |
|
85 return 0; |
|
86 return (void*)t; |
|
87 } |
|
88 |
|
89 EXPORT_C void start_thread(void* aThread) |
|
90 { |
|
91 struct cthread* t=REINTERPRET_CAST(struct cthread*,aThread); |
|
92 t->iThread.Resume(); |
|
93 } |
|
94 |
|
95 EXPORT_C int wait_for_thread(void* aThread) |
|
96 { |
|
97 struct cthread* t=REINTERPRET_CAST(struct cthread*,aThread); |
|
98 User::WaitForRequest(t->iStatus); |
|
99 int ret=t->iThread.ExitReason(); |
|
100 t->iThread.Close(); |
|
101 delete t; |
|
102 return ret; |
|
103 } |
|
104 |
|
105 EXPORT_C void* create_process(void (*aFn)(), char* aName, char* mode, int fids[3]) |
|
106 { |
|
107 #ifdef _UNICODE |
|
108 TPtrC8 ptr((TText8*)aName); |
|
109 TBuf<80> name; |
|
110 name.Copy(ptr); |
|
111 #else |
|
112 TPtrC8 name((TText8*)aName); |
|
113 #endif /* _UNICODE */ |
|
114 struct cthread* t = new cthread; |
|
115 TFileName this_exe = t->iProcess.FileName(); |
|
116 TBuf<256> cmd; |
|
117 cmd.Format(_L("%S %S"),&this_exe,&name); |
|
118 cmd.ZeroTerminate(); |
|
119 |
|
120 #ifdef _UNICODE |
|
121 wchar_t wmode[MAXPATHLEN+1]; |
|
122 mbstowcs(wmode, mode, MAXPATHLEN); |
|
123 t->pid=wpopen3((const wchar_t*)cmd.Ptr(), wmode, 0, fids); |
|
124 #else |
|
125 t->pid=popen3((const char*)cmd.Ptr(), mode, 0, fids); |
|
126 #endif |
|
127 if (t->pid < 0) |
|
128 return 0; |
|
129 User::After(1000000); // 1 Second |
|
130 return (void*)t; |
|
131 } |
|
132 |
|
133 EXPORT_C void start_process(void* /*aProcess*/) |
|
134 { |
|
135 // too late, it's already running! |
|
136 } |
|
137 |
|
138 EXPORT_C int wait_for_process(void* aProcess) |
|
139 { |
|
140 struct cthread* t=REINTERPRET_CAST(struct cthread*,aProcess); |
|
141 int exit=-1; |
|
142 int pid=waitpid(t->pid, &exit, 0); |
|
143 if (pid<0) |
|
144 return errno; |
|
145 return exit; |
|
146 } |
|
147 |
|
148 EXPORT_C int wait_for_process_id(void* aProcess, int procid, int opt, int* status) |
|
149 { |
|
150 // added function to enable calling of waitpid with specific parameters |
|
151 int pid=waitpid(procid, status, opt); |
|
152 return pid; |
|
153 } |
|
154 |
|
155 EXPORT_C int get_proc_id(void* aProcess) |
|
156 { |
|
157 // return the pid of a process |
|
158 struct cthread* t=REINTERPRET_CAST(struct cthread*,aProcess); |
|
159 return t->pid; |
|
160 } |
|
161 |
|
162 // Testing the dodgy asynchronous form of select |
|
163 |
|
164 EXPORT_C int async_ioctl(int aFid, int aCmd, void* aParam, int* status) |
|
165 { |
|
166 TRequestStatus& theStatus = *(TRequestStatus*)status; |
|
167 return ioctl(aFid,aCmd,aParam,theStatus); |
|
168 } |
|
169 |
|
170 EXPORT_C int async_ioctl_completion(int aFid, int aCmd, void* aParam, int* status) |
|
171 { |
|
172 TRequestStatus& theStatus = *(TRequestStatus*)status; |
|
173 User::WaitForRequest(theStatus); |
|
174 return ioctl_complete(aFid,aCmd,aParam,theStatus); |
|
175 } |
|
176 |
|
177 } // extern "C" |