diff --git a/main.cpp b/main.cpp index ebb358ad759dae1c80a79473b498f8d399dd3f7e..bb91a21ed4e3736ac1dc44665e4df51e3e86f55e 100644 --- a/main.cpp +++ b/main.cpp @@ -29,7 +29,7 @@ void svcHandlerThread(void *) } } - miosix_private::SyscallParameters sp=blocked->getSyscallParameters(); + todo miosix_private::SyscallParameters sp=blocked->getSyscallParameters(); if(sp.isValid()) { switch(sp.getSyscallId()) diff --git a/miosix/arch/arm7_lpc2000/lpc2138_miosix_board/interfaces-impl/portability.cpp b/miosix/arch/arm7_lpc2000/lpc2138_miosix_board/interfaces-impl/portability.cpp index eedaff4d9c127c2c9b2e7b99477bbcde1ffeef64..b42f87d72985277e5a507c01487f0df5a81375d2 100644 --- a/miosix/arch/arm7_lpc2000/lpc2138_miosix_board/interfaces-impl/portability.cpp +++ b/miosix/arch/arm7_lpc2000/lpc2138_miosix_board/interfaces-impl/portability.cpp @@ -167,7 +167,7 @@ void IRQsystemReboot() } void initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp, - void *argv) + void *argv, unsigned int gotBase) { ctxsave[0]=(unsigned int)pc;// First function arg is passed in r0 ctxsave[1]=(unsigned int)argv; @@ -178,7 +178,7 @@ void initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp, ctxsave[6]=0; ctxsave[7]=0; ctxsave[8]=0; - ctxsave[9]=0; + ctxsave[9]=gotBase; ctxsave[10]=0; ctxsave[11]=0; ctxsave[12]=0; diff --git a/miosix/arch/cortexM3_stm32/common/interfaces-impl/portability.cpp b/miosix/arch/cortexM3_stm32/common/interfaces-impl/portability.cpp index 78081e63f9ae808238f60ac8607e5853cddaff66..8eb3a83c1e90b39d4a4425e36d6786eb0bad95be 100644 --- a/miosix/arch/cortexM3_stm32/common/interfaces-impl/portability.cpp +++ b/miosix/arch/cortexM3_stm32/common/interfaces-impl/portability.cpp @@ -150,7 +150,7 @@ void IRQsystemReboot() } void initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp, - void *argv) + void *argv, unsigned int gotBase) { unsigned int *stackPtr=sp; stackPtr--; //Stack is full descending, so decrement first @@ -165,7 +165,8 @@ void initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp, *stackPtr=reinterpret_cast<unsigned long >(pc); //--> r0 ctxsave[0]=reinterpret_cast<unsigned long>(stackPtr); //--> psp - //leaving the content of r4-r11 uninitialized + ctxsave[6]=gotBase; //--> r9 + //leaving the content of r4-r8,r10-r11 uninitialized } void IRQportableStartKernel() diff --git a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability.cpp b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability.cpp index bfcd700a5f70920188764d9d06b79475ba2defc4..0148a5fb6d49c89c57e19283b7899f863cbfe990 100644 --- a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability.cpp +++ b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability.cpp @@ -169,25 +169,6 @@ void IRQsystemReboot() NVIC_SystemReset(); } -void initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp, - void *argv) -{ - unsigned int *stackPtr=sp; - stackPtr--; //Stack is full descending, so decrement first - *stackPtr=0x01000000; stackPtr--; //--> xPSR - *stackPtr=reinterpret_cast<unsigned long>( - &miosix::Thread::threadLauncher); stackPtr--; //--> pc - *stackPtr=0xffffffff; stackPtr--; //--> lr - *stackPtr=0; stackPtr--; //--> r12 - *stackPtr=0; stackPtr--; //--> r3 - *stackPtr=0; stackPtr--; //--> r2 - *stackPtr=reinterpret_cast<unsigned long >(argv); stackPtr--; //--> r1 - *stackPtr=reinterpret_cast<unsigned long >(pc); //--> r0 - - ctxsave[0]=reinterpret_cast<unsigned long>(stackPtr); //--> psp - //leaving the content of r4-r11 uninitialized -} - void initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp, void *argv, unsigned int gotBase) { @@ -204,8 +185,8 @@ void initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp, *stackPtr=reinterpret_cast<unsigned long >(pc); //--> r0 ctxsave[0]=reinterpret_cast<unsigned long>(stackPtr); //--> psp - ctxsave[6]=gotBase; //r9 - //leaving the content of r4-r11 uninitialized + ctxsave[6]=gotBase; //--> r9 + //leaving the content of r4-r8,r10-r11 uninitialized } void IRQportableStartKernel() diff --git a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability_impl.h b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability_impl.h index 629381d0b587ce33bd17e2cd32cd043fcb082a82..0e77afc6c87d4da6d00880782864c4ac3a043472 100644 --- a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability_impl.h +++ b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability_impl.h @@ -43,7 +43,7 @@ * context switch. It requires C linkage to be used inside asm statement. * Registers are saved in the following order: * *ctxsave+32 --> r11 - * *ctxsave+28 --> r10 + * *ctxsave+28 --> r10 * *ctxsave+24 --> r9 * *ctxsave+20 --> r8 * *ctxsave+16 --> r7 @@ -182,12 +182,16 @@ public: unsigned int getThirdParameter() const { return registers[2]; } /** - * Set the value that will be returned by the syscall. Invalidates - * parameters so must be called only after the syscall parameteres have - * been read. + * Set the value that will be returned by the syscall. + * Invalidates parameters so must be called only after the syscall + * parameteres have been read. * \param ret value that will be returned by the syscall. */ - void setReturnValue(unsigned int ret) { registers[0]=ret; } + void setReturnValue(unsigned int ret) + { + if(valid) registers[0]=ret; + valid=false; + } /** * Invalidate the object. Meant to be called after the syscall has been @@ -200,9 +204,6 @@ private: bool valid; }; -void initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp, - void *argv, unsigned int gotBase); - #endif //WITH_PROCESSES /** diff --git a/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability.cpp b/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability.cpp index c82fa7f5b11a057816feec6da4c981a71926944b..4c23fb5db59b365ed4298159db84f86507a0d593 100644 --- a/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability.cpp +++ b/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability.cpp @@ -150,7 +150,7 @@ void IRQsystemReboot() } void initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp, - void *argv) + void *argv, unsigned int gotBase) { unsigned int *stackPtr=sp; stackPtr--; //Stack is full descending, so decrement first @@ -165,7 +165,8 @@ void initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp, *stackPtr=reinterpret_cast<unsigned long >(pc); //--> r0 ctxsave[0]=reinterpret_cast<unsigned long>(stackPtr); //--> psp - //leaving the content of r4-r11 uninitialized + ctxsave[6]=gotBase; //--> r9 + //leaving the content of r4-r8,r10-r11 uninitialized } void IRQportableStartKernel() diff --git a/miosix/config/miosix_settings.h b/miosix/config/miosix_settings.h index f764a3cdec62d725671f995cd3c884cd23aa6632..eda6dc4fd3c35564ae15f90ab0716f1a56a97c09 100644 --- a/miosix/config/miosix_settings.h +++ b/miosix/config/miosix_settings.h @@ -69,6 +69,10 @@ namespace miosix { /// isolation of processes #define WITH_PROCESSES +#if defined(WITH_PROCESSES) && defined(__NO_EXCEPTIONS) +#error Processes required C++ exception support +#endif //defined(WITH_PROCESSES) && defined(__NO_EXCEPTIONS) + /// Maximum size of the RAM image of a process. If a program requires more /// the kernel will not run it const int MAX_PROCESS_IMAGE_SIZE=20*1024; @@ -77,6 +81,12 @@ const int MAX_PROCESS_IMAGE_SIZE=20*1024; /// size the kernel will not run it const int MIN_PROCESS_STACK_SIZE=2*1024; +/// Every userspace thread has two stacks, one for when it is running in +/// userspace and one for when it is running in kernelspace (that is, while it +/// is executing system calls). This is the size of the stack for when the +/// thread is running in kernelspace +const int SYSTEM_MODE_PROCESS_STACK_SIZE=2*1024; + // // Filesystem options // diff --git a/miosix/interfaces/portability.h b/miosix/interfaces/portability.h index b1c7a807b41ff8f63e37dede2805df712f1cf9ab..3c98a8fcf16ccf94b3ae7b50cca282b8a6465f9b 100644 --- a/miosix/interfaces/portability.h +++ b/miosix/interfaces/portability.h @@ -95,9 +95,11 @@ inline void doYield(); * ctxsave * \param argv starting data passed to newly created thread, used to initialize * ctxsave + * \param gotBase base address of the global offset table, for userspace + * processes */ void initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp, - void *argv); + void *argv, unsigned int gotBase=0); /** * \internal diff --git a/miosix/kernel/kernel.cpp b/miosix/kernel/kernel.cpp index 60206d9a9d8f7d7fd8a432de6f76ead83a6a7593..1d12adbe02d368c6adb4274c643e20e600a72730 100644 --- a/miosix/kernel/kernel.cpp +++ b/miosix/kernel/kernel.cpp @@ -675,6 +675,14 @@ const int Thread::getStackSize() return cur->stacksize; } +miosix_private::SyscallParameters Thread::getSyscallParameters() +{ + unsigned int *context=const_cast<unsigned int*>(cur->ctxsave); + miosix_private::SyscallParameters result(context); + if(cur->pid==0) result.invalidate(); + return result; +} + void Thread::threadLauncher(void *(*threadfunc)(void*), void *argv) { void *result=0; diff --git a/miosix/kernel/kernel.h b/miosix/kernel/kernel.h index 89fb8335a12c137299d01c3d05c210baafdb730a..af3dc0c130113ecbc8dc3dd5213bc0bd46129410 100644 --- a/miosix/kernel/kernel.h +++ b/miosix/kernel/kernel.h @@ -37,6 +37,7 @@ #include <cstdlib> #include <new> #include <functional> +#include <sys/types.h> // some pthread functions are friends of Thread #include <pthread.h> @@ -393,6 +394,7 @@ struct SleepData; class MemoryProfiling; class Mutex; class ConditionVariable; +class Process; /** * This class represents a thread. It has methods for creating, deleting and @@ -466,11 +468,6 @@ public: static Thread *create(void (*startfunc)(void *), unsigned int stacksize, Priority priority=Priority(), void *argv=NULL, unsigned short options=DEFAULT); - - static Thread *createWithGotBase(void *(*startfunc)(void *), - unsigned int stacksize, - Priority priority, void *argv, - unsigned short options,unsigned int *gotBase); /** * When called, suggests the kernel to pause the current thread, and run @@ -699,10 +696,7 @@ public: /** * \return the syscall parameters */ - miosix_private::SyscallParameters getSyscallParameters() - { - return miosix_private::SyscallParameters(ctxsave); - } + static miosix_private::SyscallParameters getSyscallParameters(); #endif //WITH_PROCESSES private: @@ -821,6 +815,12 @@ private: * \return true if stack is handled separately and must not be deleted */ bool hasExternStack() const { return flags & EXTERN_STACK; } + + /** + * \return true if the thread is running unprivileged inside a process. + * Only threads whose pid is not zero can run in userspace + */ + bool isInUserspace() const { return flags & USERSPACE; } private: ///\internal Thread is in the wait status. A call to wakeup will change @@ -850,9 +850,28 @@ private: ///\internal Thread stack is handled separately and must not be freed ///at thread termination static const unsigned int EXTERN_STACK=1<<7; + + ///\internal Thread is running in userspace + static const unsigned int USERSPACE=1<<7; unsigned short flags;///<\internal flags are stored here }; + + /** + * + * \param startfunc + * \param stacksize + * \param priority + * \param argv + * \param options + * \param gotBase + * \return + */ + static Thread *createWithGotBase(void *(*startfunc)(void *), + unsigned int stacksize, + Priority priority, void *argv, + unsigned short options,unsigned int *gotBase, + pid_t pid, unsigned int entry, unsigned int *base); /** * Constructor, initializes thread data. @@ -912,7 +931,7 @@ private: #ifdef WITH_PROCESSES ///Id of the process to which this thread belongs. Zero if a kernel thread. ///More threads can have the same pid if they run in the same process - int pid; + pid_t pid; ///Pointer to the set of saved registers for when the thread is running in ///user mode. For kernel threads (i.e, threads whose pid is zero) this ///pointer is null @@ -932,10 +951,8 @@ private: friend void startKernel(); //Needs threadLauncher friend void miosix_private::initCtxsave(unsigned int *ctxsave, - void *(*pc)(void *), unsigned int *sp, void *argv); - //Needs threadLauncher - friend void miosix_private::initCtxsave(unsigned int *ctxsave, - void *(*pc)(void *), unsigned int *sp, void *argv,unsigned int gotBase); + void *(*pc)(void *), unsigned int *sp, void *argv, + unsigned int gotBase); //Needs access to priority, savedPriority, mutexLocked and flags. friend class Mutex; //Needs access to flags @@ -954,6 +971,8 @@ private: friend int ::pthread_cond_broadcast(pthread_cond_t *cond); //Needs access to exData friend class ExceptionHandlingAccessor; + //Needs access to initializeUserspaceContext() + friend class Process; }; /** diff --git a/miosix/kernel/process.cpp b/miosix/kernel/process.cpp index b98de8b1f16b6562b41a626088a772dd209a75ba..e7af161750e2942ced366031deb017421c85e901 100644 --- a/miosix/kernel/process.cpp +++ b/miosix/kernel/process.cpp @@ -25,12 +25,70 @@ * along with this program; if not, see <http://www.gnu.org/licenses/> * ***************************************************************************/ +#include <stdexcept> #include "process.h" +using namespace std; + #ifdef WITH_PROCESSES namespace miosix { + +// +// class Process +// + +Process *Process::create(const ElfProgram& program) +{ + Process *proc=new Process; + pid_t pid; + proc->image.load(program); + { + PauseKernelLock dLock; + pid=PKgetNewPid(); + processes[pid]=proc; + } + Thread *thr=Thread::create(Process::start, + SYSTEM_MODE_PROCESS_STACK_SIZE,MAIN_PRIORITY,0,Thread::JOINABLE,pid, + program.getEntryPoint(),proc->image.getProcessBasePointer()); + if(thr==0) + { + { + PauseKernelLock dLock; + processes.erase(pid); + } + throw runtime_error("Thread creation failed"); + } + try { + proc->threads.push_back(thr); + } catch(...) { + { + PauseKernelLock dLock; + processes.erase(pid); + } + throw; + } +} + +void *Process::start(void *argv) +{ + //TODO +} + +pid_t Process::PKgetNewPid() +{ + for(;;pidCounter++) + { + if(pidCounter==0) continue; //Zero is not a valid pid + map<pid_t,Process *>::iterator it=processes.find(pidCounter); + if(it!=processes.end()) continue; //Pid number already used + return pidCounter++; + } +} + +map<pid_t,Process *> Process::processes; +pid_t Process::pidCounter=1; } //namespace miosix diff --git a/miosix/kernel/process.h b/miosix/kernel/process.h index 4003fd8a87dcb9d41b001db8fba4ee33d8b16a8d..bb5c0b614b43294bc9672bd25efbcdf59e027214 100644 --- a/miosix/kernel/process.h +++ b/miosix/kernel/process.h @@ -28,6 +28,11 @@ #ifndef PROCESS_H #define PROCESS_H +#include <vector> +#include <map> +#include <sys/types.h> +#include "kernel.h" +#include "elf_program.h" #include "config/miosix_settings.h" #ifdef WITH_PROCESSES @@ -38,12 +43,28 @@ class Process { public: + static Process *create(const ElfProgram& program); + private: - + + static void *start(void *argv); + + static pid_t PKgetNewPid(); + + Process(const Process&); + Process& operator= (const Process&); + + ProcessImage image; ///<The RAM image of a process + std::vector<Thread *> threads; ///<Threads that belong to the process + + ///Maps the pid to the Process instance + static std::map<pid_t,Process *> processes; + ///Used to assign a new pid to a process + static pid_t pidCounter; }; } //namespace miosix -#endif WITH_PROCESSES +#endif //WITH_PROCESSES #endif //PROCESS_H diff --git a/miosix_np_2/nbproject/configurations.xml b/miosix_np_2/nbproject/configurations.xml index f467046124be306ffd64dd284cb9e78e832e2f0e..3cc8368d0b4e9685b12686bcd5242b6a29d7d2d1 100644 --- a/miosix_np_2/nbproject/configurations.xml +++ b/miosix_np_2/nbproject/configurations.xml @@ -5,6 +5,7 @@ <df name="app_template"> <in>crt0.s</in> <in>main.c</in> + <in>prog3.h</in> </df> <df name="miosix"> <df name="arch"> @@ -278,11 +279,16 @@ <in>tick_interrupt.h</in> </df> <in>buffer_queue.h</in> + <in>elf_program.cpp</in> + <in>elf_program.h</in> + <in>elf_types.h</in> <in>error.cpp</in> <in>error.h</in> <in>kernel.cpp</in> <in>kernel.h</in> <in>logging.h</in> + <in>process.cpp</in> + <in>process.h</in> <in>pthread.cpp</in> <in>pthread_private.h</in> <in>stage_2_boot.cpp</in> @@ -310,13 +316,7 @@ </df> <df name="miosix_np_2"> </df> - <in>elf_program.cpp</in> - <in>elf_program.h</in> - <in>elf_types.h</in> <in>main.cpp</in> - <in>prog1.h</in> - <in>svc.s</in> - <in>test_driver.cpp</in> </df> <logicalFolder name="ExternalFiles" displayName="Important Files"