sl@0: // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // C routines for creating EPOC32 threads sl@0: // sl@0: // sl@0: sl@0: #include sl@0: #include /* for SpawnPosixServerThread */ sl@0: #include sl@0: #include /* for popen3 */ sl@0: #include /* for mbstowcs */ sl@0: #include "CTEST.H" sl@0: #include /* for errno */ sl@0: #include sl@0: sl@0: typedef void (*FUNC)(); sl@0: sl@0: struct cthread sl@0: { sl@0: RThread iThread; sl@0: RProcess iProcess; sl@0: TRequestStatus iStatus; sl@0: int pid; sl@0: }; sl@0: sl@0: TInt threadhelper (TAny* aFn) sl@0: { sl@0: CTrapCleanup::New(); sl@0: FUNC f=(FUNC)aFn; sl@0: (*f)(); sl@0: return 0; sl@0: } sl@0: sl@0: #if defined(__WINS__) sl@0: sl@0: IMPORT_C void NewProcessId(); // WINS bodges for multiple "processes" sl@0: IMPORT_C void NextProcessFn(TAny*); sl@0: sl@0: TInt processhelper (TAny* aFn) sl@0: { sl@0: // Do the MCRT0.OBJ things straight away sl@0: NewProcessId(); sl@0: SpawnPosixServerThread(); sl@0: char wd[80]; sl@0: getcwd(wd, sizeof(wd)); // connect to CPosixServer sl@0: return threadhelper(aFn); sl@0: } sl@0: sl@0: #endif //__WINS__ sl@0: sl@0: sl@0: extern "C" { sl@0: sl@0: EXPORT_C int start_posix_server() sl@0: { sl@0: start_redirection_server(); sl@0: return SpawnPosixServerThread(); sl@0: } sl@0: sl@0: EXPORT_C void* create_thread(void (*aFn)(), char* aName) sl@0: { sl@0: #ifdef _UNICODE sl@0: TPtrC8 ptr((TText8*)aName); sl@0: TBuf<80> name; sl@0: name.Copy(ptr); sl@0: #else sl@0: TPtrC8 name((TText8*)aName); sl@0: #endif /* _UNICODE */ sl@0: struct cthread* t = new cthread; sl@0: // 16k stack, share parent's heap sl@0: TInt err=t->iThread.Create(name, threadhelper, 0x4000, NULL, (TAny*)aFn); sl@0: t->iThread.Logon(t->iStatus); sl@0: if (err!= KErrNone) sl@0: return 0; sl@0: return (void*)t; sl@0: } sl@0: sl@0: EXPORT_C void start_thread(void* aThread) sl@0: { sl@0: struct cthread* t=REINTERPRET_CAST(struct cthread*,aThread); sl@0: t->iThread.Resume(); sl@0: } sl@0: sl@0: EXPORT_C int wait_for_thread(void* aThread) sl@0: { sl@0: struct cthread* t=REINTERPRET_CAST(struct cthread*,aThread); sl@0: User::WaitForRequest(t->iStatus); sl@0: int ret=t->iThread.ExitReason(); sl@0: t->iThread.Close(); sl@0: delete t; sl@0: return ret; sl@0: } sl@0: sl@0: EXPORT_C void* create_process(void (*aFn)(), char* aName, char* mode, int fids[3]) sl@0: { sl@0: #ifdef _UNICODE sl@0: TPtrC8 ptr((TText8*)aName); sl@0: TBuf<80> name; sl@0: name.Copy(ptr); sl@0: #else sl@0: TPtrC8 name((TText8*)aName); sl@0: #endif /* _UNICODE */ sl@0: struct cthread* t = new cthread; sl@0: TFileName this_exe = t->iProcess.FileName(); sl@0: TBuf<256> cmd; sl@0: cmd.Format(_L("%S %S"),&this_exe,&name); sl@0: cmd.ZeroTerminate(); sl@0: sl@0: #ifdef _UNICODE sl@0: wchar_t wmode[MAXPATHLEN+1]; sl@0: mbstowcs(wmode, mode, MAXPATHLEN); sl@0: t->pid=wpopen3((const wchar_t*)cmd.Ptr(), wmode, 0, fids); sl@0: #else sl@0: t->pid=popen3((const char*)cmd.Ptr(), mode, 0, fids); sl@0: #endif sl@0: if (t->pid < 0) sl@0: return 0; sl@0: User::After(1000000); // 1 Second sl@0: return (void*)t; sl@0: } sl@0: sl@0: EXPORT_C void start_process(void* /*aProcess*/) sl@0: { sl@0: // too late, it's already running! sl@0: } sl@0: sl@0: EXPORT_C int wait_for_process(void* aProcess) sl@0: { sl@0: struct cthread* t=REINTERPRET_CAST(struct cthread*,aProcess); sl@0: int exit=-1; sl@0: int pid=waitpid(t->pid, &exit, 0); sl@0: if (pid<0) sl@0: return errno; sl@0: return exit; sl@0: } sl@0: sl@0: EXPORT_C int wait_for_process_id(void* aProcess, int procid, int opt, int* status) sl@0: { sl@0: // added function to enable calling of waitpid with specific parameters sl@0: int pid=waitpid(procid, status, opt); sl@0: return pid; sl@0: } sl@0: sl@0: EXPORT_C int get_proc_id(void* aProcess) sl@0: { sl@0: // return the pid of a process sl@0: struct cthread* t=REINTERPRET_CAST(struct cthread*,aProcess); sl@0: return t->pid; sl@0: } sl@0: sl@0: // Testing the dodgy asynchronous form of select sl@0: sl@0: EXPORT_C int async_ioctl(int aFid, int aCmd, void* aParam, int* status) sl@0: { sl@0: TRequestStatus& theStatus = *(TRequestStatus*)status; sl@0: return ioctl(aFid,aCmd,aParam,theStatus); sl@0: } sl@0: sl@0: EXPORT_C int async_ioctl_completion(int aFid, int aCmd, void* aParam, int* status) sl@0: { sl@0: TRequestStatus& theStatus = *(TRequestStatus*)status; sl@0: User::WaitForRequest(theStatus); sl@0: return ioctl_complete(aFid,aCmd,aParam,theStatus); sl@0: } sl@0: sl@0: } // extern "C"