diff --git a/main.cpp b/main.cpp
index bb91a21ed4e3736ac1dc44665e4df51e3e86f55e..74a32a0715507e3519ec176ee749f3501a28e5d3 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,60 +1,12 @@
 
 #include <cstdio>
-#include <cassert>
 #include "miosix.h"
-#include "kernel/elf_program.h"
+#include "kernel/process.h"
 #include "app_template/prog3.h"
 
 using namespace std;
 using namespace miosix;
 
-Thread *svcHandler=0;
-Thread *blocked=0;
-
-void svcHandlerThread(void *)
-{
-    for(;;)
-    {
-        {
-            FastInterruptDisableLock dLock;
-            blocked=0;
-            for(;;)
-            {
-                if(blocked!=0) break;
-                Thread::getCurrentThread()->IRQwait();
-                {
-                    FastInterruptEnableLock eLock(dLock);
-                    Thread::yield();
-                }
-            }
-        }
-        
-        todo miosix_private::SyscallParameters sp=blocked->getSyscallParameters();
-        if(sp.isValid())
-        {
-            switch(sp.getSyscallId())
-            {
-                case 1:
-                    iprintf("Exit %d\n",sp.getFirstParameter());
-                    break;
-                case 2:
-//                    iprintf("Write called %d %x %d\n",
-//                            sp.getFirstParameter(),
-//                            sp.getSecondParameter(),
-//                            sp.getThirdParameter());
-                    sp.setReturnValue(write(sp.getFirstParameter(),
-                          (const char*)sp.getSecondParameter(),
-                          sp.getThirdParameter()));
-                    blocked->wakeup();
-                    break;
-            }
-        } else {
-            iprintf("Unexpected invalid syscall\n");
-        }
-        sp.invalidate();
-    }
-}
-
 void ledThread(void *)
 {
     for(;;)
@@ -69,15 +21,10 @@ void ledThread(void *)
 int main()
 {
     Thread::create(ledThread,STACK_MIN);
-    svcHandler=Thread::create(svcHandlerThread,2048);
     
     getchar();
     
     ElfProgram prog(reinterpret_cast<const unsigned int*>(main_elf),main_elf_len);
-    ProcessImage pi;
-    pi.load(prog);
-    void *(*entry)(void*)=reinterpret_cast<void *(*)(void*)>(prog.getEntryPoint());
-    Thread::createWithGotBase(entry,2048,1,0,0,pi.getProcessBasePointer());
-    
+    Process::create(prog);
     for(;;) Thread::sleep(1000);
 }
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 b42f87d72985277e5a507c01487f0df5a81375d2..227961ccafa54dd8e45995a2a74fdc120f43df70 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, unsigned int gotBase)
+            void *argv)
 {
     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]=gotBase;
+    ctxsave[9]=0;
     ctxsave[10]=0;
     ctxsave[11]=0;
     ctxsave[12]=0;
@@ -189,6 +189,33 @@ void initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp,
     ctxsave[16]=0x1f;//thread starts in system mode with irq and fiq enabled.
 }
 
+#ifdef WITH_PROCESSES
+
+void initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp,
+            void *argv, unsigned int *gotBase)
+{
+    ctxsave[0]=(unsigned int)argv;
+    ctxsave[1]=0;
+    ctxsave[2]=0;
+    ctxsave[3]=0;
+    ctxsave[4]=0;
+    ctxsave[5]=0;
+    ctxsave[6]=0;
+    ctxsave[7]=0;
+    ctxsave[8]=0;
+    ctxsave[9]=(unsigned int)gotBase;
+    ctxsave[10]=0;
+    ctxsave[11]=0;
+    ctxsave[12]=0;
+    ctxsave[13]=(unsigned int)sp;//Initialize the thread's stack pointer
+    ctxsave[14]=0xffffffff;//threadLauncher never returns, so lr is not important
+    //Initialize the thread's program counter to the beginning of the entry point
+    ctxsave[15]=(unsigned int)pc;
+    ctxsave[16]=0x1f;//thread starts in system mode with irq and fiq enabled.
+}
+
+#endif //WITH_PROCESSES
+
 void IRQportableStartKernel()
 {
     PCONP|=(1<<1);//Enable TIMER0
diff --git a/miosix/arch/arm7_lpc2000/lpc2138_miosix_board/interfaces-impl/portability_impl.h b/miosix/arch/arm7_lpc2000/lpc2138_miosix_board/interfaces-impl/portability_impl.h
index ffbfd86cfdb3bce060bb5d82bb0be3b20b7d8ed9..af14a0deee76b30a7d24f990b20c2df0b6dc474a 100644
--- a/miosix/arch/arm7_lpc2000/lpc2138_miosix_board/interfaces-impl/portability_impl.h
+++ b/miosix/arch/arm7_lpc2000/lpc2138_miosix_board/interfaces-impl/portability_impl.h
@@ -181,7 +181,9 @@ namespace miosix_private {
 
 inline void doYield()
 {
-    asm volatile("swi 0");
+    asm volatile("movs  r3, #0\n\t"
+                 "swi   0"
+                 :::"r3");
 }
 
 inline void doDisableInterrupts()
diff --git a/miosix/arch/cortexM3_stm32/common/interfaces-impl/portability.cpp b/miosix/arch/cortexM3_stm32/common/interfaces-impl/portability.cpp
index 8eb3a83c1e90b39d4a4425e36d6786eb0bad95be..d11081e9d0aebb3e4a409b7e8e8cbc23e5470f9b 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, unsigned int gotBase)
+        void *argv)
 {
     unsigned int *stackPtr=sp;
     stackPtr--; //Stack is full descending, so decrement first
@@ -165,10 +165,32 @@ 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
+}
+
+#ifdef WITH_PROCESSES
+
+void initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp,
+        void *argv, unsigned int *gotBase)
+{
+    unsigned int *stackPtr=sp;
+    stackPtr--; //Stack is full descending, so decrement first
+    *stackPtr=0x01000000; stackPtr--;                                 //--> xPSR
+    *stackPtr=reinterpret_cast<unsigned long>(pc); stackPtr--;        //--> pc
+    *stackPtr=0xffffffff; stackPtr--;                                 //--> lr
+    *stackPtr=0; stackPtr--;                                          //--> r12
+    *stackPtr=0; stackPtr--;                                          //--> r3
+    *stackPtr=0; stackPtr--;                                          //--> r2
+    *stackPtr=0; stackPtr--;                                          //--> r1
+    *stackPtr=reinterpret_cast<unsigned long >(argv);                 //--> r0
+
+    ctxsave[0]=reinterpret_cast<unsigned long>(stackPtr);             //--> psp
+    ctxsave[6]=reinterpret_cast<unsigned long>(gotBase);              //--> r9 
     //leaving the content of r4-r8,r10-r11 uninitialized
 }
 
+#endif //WITH_PROCESSES
+
 void IRQportableStartKernel()
 {
     //Enable fault handlers
diff --git a/miosix/arch/cortexM3_stm32/common/interfaces-impl/portability_impl.h b/miosix/arch/cortexM3_stm32/common/interfaces-impl/portability_impl.h
index c6686a632e24ecbad9eeab1f91bcf7a2b6216e23..9f46d1bce8f077cba6666b65eaf2705272ed5196 100644
--- a/miosix/arch/cortexM3_stm32/common/interfaces-impl/portability_impl.h
+++ b/miosix/arch/cortexM3_stm32/common/interfaces-impl/portability_impl.h
@@ -102,7 +102,9 @@ namespace miosix_private {
 
 inline void doYield()
 {
-    asm volatile("svc 0");
+    asm volatile("movs r3, #0\n\t"
+                 "svc  0"
+                 :::"r3");
 }
 
 inline void doDisableInterrupts()
diff --git a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability.cpp b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability.cpp
index 0148a5fb6d49c89c57e19283b7899f863cbfe990..a73ca68d92bbbb9ae2d430c4bab9d0e2edc261d8 100644
--- a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability.cpp
+++ b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability.cpp
@@ -85,9 +85,6 @@ void TIM3_IRQHandler()
 }
 #endif //SCHED_TYPE_CONTROL_BASED
 
-extern miosix::Thread *svcHandler;
-extern miosix::Thread *blocked;
-
 namespace miosix_private {
 
 /**
@@ -121,18 +118,11 @@ void ISR_yield()
     //it is a simple yield, otherwise pause the thread and wake the svcHandler
     unsigned int threadSp=ctxsave[0];
     unsigned int *processStack=reinterpret_cast<unsigned int*>(threadSp);
-    if(processStack[3]!=0)
-    {
-        blocked=const_cast<miosix::Thread*>(miosix::cur);
-        blocked->IRQwait();
-        if(svcHandler==0) miosix::errorHandler(miosix::UNEXPECTED);
-        svcHandler->IRQwakeup();
-    }
-    #endif //WITH_PROCESSES
-
-    //Note: this still has to be called even when r3!=0, since without this
-    //call the blocked->IRQwait() would not become effective
+    if(processStack[3]!=0) miosix::Thread::IRQswitchToKernelspace();
+    else miosix::Scheduler::IRQfindNextThread();
+    #else //WITH_PROCESSES
     miosix::Scheduler::IRQfindNextThread();
+    #endif //WITH_PROCESSES
 }
 
 #ifdef SCHED_TYPE_CONTROL_BASED
@@ -153,6 +143,8 @@ void ISR_auxTimer()
 
 void IRQstackOverflowCheck()
 {
+    //TODO: stack checking for userspace
+    if(const_cast<miosix::Thread*>(miosix::cur)->flags.isInUserspace()) return;
     const unsigned int watermarkSize=miosix::WATERMARK_LEN/sizeof(unsigned int);
     for(unsigned int i=0;i<watermarkSize;i++)
     {
@@ -170,7 +162,7 @@ void IRQsystemReboot()
 }
 
 void initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp,
-        void *argv, unsigned int gotBase)
+        void *argv)
 {
     unsigned int *stackPtr=sp;
     stackPtr--; //Stack is full descending, so decrement first
@@ -185,10 +177,32 @@ 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
+}
+
+#ifdef WITH_PROCESSES
+
+void initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp,
+        void *argv, unsigned int *gotBase)
+{
+    unsigned int *stackPtr=sp;
+    stackPtr--; //Stack is full descending, so decrement first
+    *stackPtr=0x01000000; stackPtr--;                                 //--> xPSR
+    *stackPtr=reinterpret_cast<unsigned long>(pc); stackPtr--;        //--> pc
+    *stackPtr=0xffffffff; stackPtr--;                                 //--> lr
+    *stackPtr=0; stackPtr--;                                          //--> r12
+    *stackPtr=0; stackPtr--;                                          //--> r3
+    *stackPtr=0; stackPtr--;                                          //--> r2
+    *stackPtr=0; stackPtr--;                                          //--> r1
+    *stackPtr=reinterpret_cast<unsigned long >(argv);                 //--> r0
+
+    ctxsave[0]=reinterpret_cast<unsigned long>(stackPtr);             //--> psp
+    ctxsave[6]=reinterpret_cast<unsigned long>(gotBase);              //--> r9                                               //--> r9
     //leaving the content of r4-r8,r10-r11 uninitialized
 }
 
+#endif //WITH_PROCESSES
+
 void IRQportableStartKernel()
 {
     //Enable fault handlers
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 0e77afc6c87d4da6d00880782864c4ac3a043472..94b8f658dd1081f05f3f31cb27c7046dd62d7e81 100644
--- a/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability_impl.h
+++ b/miosix/arch/cortexM3_stm32f2/common/interfaces-impl/portability_impl.h
@@ -104,7 +104,7 @@ inline void doYield()
 {
     asm volatile("movs r3, #0\n\t"
                  "svc  0"
-                 :::"r1");
+                 :::"r3");
 }
 
 inline void doDisableInterrupts()
diff --git a/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability.cpp b/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability.cpp
index 4c23fb5db59b365ed4298159db84f86507a0d593..89ca2132d189fe51bf41ebe65efe3c8ebda3d846 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, unsigned int gotBase)
+        void *argv)
 {
     unsigned int *stackPtr=sp;
     stackPtr--; //Stack is full descending, so decrement first
@@ -165,10 +165,32 @@ 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
+}
+
+#ifdef WITH_PROCESSES
+
+void initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp,
+        void *argv, unsigned int *gotBase)
+{
+    unsigned int *stackPtr=sp;
+    stackPtr--; //Stack is full descending, so decrement first
+    *stackPtr=0x01000000; stackPtr--;                                 //--> xPSR
+    *stackPtr=reinterpret_cast<unsigned long>(pc); stackPtr--;        //--> pc
+    *stackPtr=0xffffffff; stackPtr--;                                 //--> lr
+    *stackPtr=0; stackPtr--;                                          //--> r12
+    *stackPtr=0; stackPtr--;                                          //--> r3
+    *stackPtr=0; stackPtr--;                                          //--> r2
+    *stackPtr=0; stackPtr--;                                          //--> r1
+    *stackPtr=reinterpret_cast<unsigned long >(argv);                 //--> r0
+
+    ctxsave[0]=reinterpret_cast<unsigned long>(stackPtr);             //--> psp
+    ctxsave[6]=reinterpret_cast<unsigned long>(gotBase);              //--> r9 
     //leaving the content of r4-r8,r10-r11 uninitialized
 }
 
+#endif //WITH_PROCESSES
+
 void IRQportableStartKernel()
 {
     //Enable fault handlers
diff --git a/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability_impl.h b/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability_impl.h
index 5fcc019b48c22748b3466d29368a89a918708327..e40061aa5df985f07b8f1e316cc554d79f25f1cb 100644
--- a/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability_impl.h
+++ b/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability_impl.h
@@ -102,7 +102,9 @@ namespace miosix_private {
 
 inline void doYield()
 {
-    asm volatile("svc 0");
+    asm volatile("movs r3, #0\n\t"
+                 "svc  0"
+                 :::"r3");
 }
 
 inline void doDisableInterrupts()
diff --git a/miosix/interfaces/portability.h b/miosix/interfaces/portability.h
index 3c98a8fcf16ccf94b3ae7b50cca282b8a6465f9b..10e806f705d6a8528b753349fe17becfc46935af 100644
--- a/miosix/interfaces/portability.h
+++ b/miosix/interfaces/portability.h
@@ -95,11 +95,32 @@ inline void doYield();
  * ctxsave
  * \param argv starting data passed to newly created thread, used to initialize
  * ctxsave
+ */
+void initCtxsave(unsigned int *ctxsave, void *(*pc)(void *), unsigned int *sp,
+        void *argv);
+
+#ifdef WITH_PROCESSES
+
+/**
+ * \internal
+ * Initializes a ctxsave array when a thread is created.
+ * This version is to initialize the userspace context of processes.
+ * It is used by the kernel, and should not be used by end users.
+ * \param ctxsave a pointer to a field ctxsave inside a Thread class that need
+ * to be filled
+ * \param pc starting program counter of newly created thread, used to
+ * initialize ctxsave
+ * \param sp starting stack pointer of newly created thread, used to initialize
+ * 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, unsigned int gotBase=0);
+        void *argv, unsigned int *gotBase);
+
+#endif //WITH_PROCESSES
 
 /**
  * \internal
diff --git a/miosix/kernel/elf_program.cpp b/miosix/kernel/elf_program.cpp
index 523052e22d57c89101614ee31ab5b9c7952ceb29..08cbfa059d7e9033049d71abd9216e577cb425d4 100644
--- a/miosix/kernel/elf_program.cpp
+++ b/miosix/kernel/elf_program.cpp
@@ -205,12 +205,13 @@ bool ElfProgram::validateDynamicSegment(const Elf32_Phdr *dynamic,
 // class ProcessImage
 //
 
-void ProcessImage::load(ElfProgram& program)
+void ProcessImage::load(const ElfProgram& program)
 {
     if(image) delete[] image;
     
     //TODO: add in elf file a field with the true image size
     image=new unsigned int[MAX_PROCESS_IMAGE_SIZE/4];
+    size=MAX_PROCESS_IMAGE_SIZE;
     const unsigned int base=program.getElfBase();
     const Elf32_Phdr *phdr=program.getProgramHeaderTable();
     Elf32_Addr dtRel=0;
diff --git a/miosix/kernel/elf_program.h b/miosix/kernel/elf_program.h
index 87e3d116a570552d13c6a87e6307af348e1459ad..835d6a4dc26c25c4cdac957ce444158ac8a05e31 100644
--- a/miosix/kernel/elf_program.h
+++ b/miosix/kernel/elf_program.h
@@ -132,7 +132,7 @@ public:
      * the process, including copying .data, zeroing .bss and performing
      * relocations
      */
-    void load(ElfProgram& program);
+    void load(const ElfProgram& program);
     
     /**
      * \return a pointer to the base of the program image
diff --git a/miosix/kernel/kernel.cpp b/miosix/kernel/kernel.cpp
index 1d12adbe02d368c6adb4274c643e20e600a72730..c02d7d0ef11399180f40465b2f00fa1266e7d7ca 100644
--- a/miosix/kernel/kernel.cpp
+++ b/miosix/kernel/kernel.cpp
@@ -366,75 +366,6 @@ Thread *Thread::create(void (*startfunc)(void *), unsigned int stacksize,
             stacksize,priority,argv,options);
 }
 
-Thread *Thread::createWithGotBase(void *(*startfunc)(void *),
-                            unsigned int stacksize,
-                            Priority priority, void *argv,
-                            unsigned short options,unsigned int *gotBase)
-{
-        //Check to see if input parameters are valid
-    if(priority.validate()==false || stacksize<STACK_MIN)
-    {
-        errorHandler(INVALID_PARAMETERS);
-        return NULL;
-    }
-    //If stacksize is not divisible by 4, round it to a number divisible by 4
-    stacksize &= ~0x3;
-    
-    //Allocate memory for the thread, return if fail
-    unsigned int *base;
-    Thread *thread;
-    #ifdef __NO_EXCEPTIONS
-    base=new int[(stacksize+WATERMARK_LEN+CTXSAVE_ON_STACK)/4];
-    thread=new Thread(base,stacksize);
-    #else //__NO_EXCEPTIONS
-    try {
-        base=new unsigned int[(stacksize+WATERMARK_LEN+CTXSAVE_ON_STACK)/4];
-    } catch(std::bad_alloc&)
-    {
-        errorHandler(OUT_OF_MEMORY);
-        return NULL;//Error
-    }
-    try {
-        thread=new Thread(base,stacksize);
-    } catch(std::bad_alloc&)
-    {
-        delete[] base;
-        errorHandler(OUT_OF_MEMORY);
-        return NULL;//Error
-    }
-    #endif //__NO_EXCEPTIONS
-
-    //Fill watermark and stack
-    memset(base, WATERMARK_FILL, WATERMARK_LEN);
-    base+=WATERMARK_LEN/sizeof(unsigned int);
-    memset(base, STACK_FILL, stacksize);
-
-    //On some architectures some registers are saved on the stack, therefore
-    //initCtxsave *must* be called after filling the stack.
-    unsigned int *topOfStack=
-        thread->watermark+(stacksize+WATERMARK_LEN+CTXSAVE_ON_STACK)/4;
-    miosix_private::initCtxsave(thread->ctxsave,startfunc,topOfStack,argv,
-            (unsigned int)gotBase);
-
-    if((options & JOINABLE)==0) thread->flags.IRQsetDetached();
-    
-    //Add thread to thread list
-    {
-        //Handling the list of threads, critical section is required
-        PauseKernelLock lock;
-        if(Scheduler::PKaddThread(thread,priority)==false)
-        {
-            //Reached limit on number of threads
-            delete thread;
-            return NULL;
-        }
-    }
-    #ifdef SCHED_TYPE_EDF
-    if(isKernelRunning()) yield(); //The new thread might have a closer deadline
-    #endif //SCHED_TYPE_EDF
-    return thread;
-}
-
 void Thread::yield()
 {
     miosix_private::doYield();
@@ -675,14 +606,16 @@ const int Thread::getStackSize()
     return cur->stacksize;
 }
 
-miosix_private::SyscallParameters Thread::getSyscallParameters()
+#ifdef WITH_PROCESSES
+
+void Thread::IRQswitchToKernelspace()
 {
-    unsigned int *context=const_cast<unsigned int*>(cur->ctxsave);
-    miosix_private::SyscallParameters result(context);
-    if(cur->pid==0) result.invalidate();
-    return result;
+    const_cast<Thread*>(cur)->flags.IRQsetUserspace(false);
+    ::ctxsave=cur->ctxsave;
 }
 
+#endif //WITH_PROCESSES
+
 void Thread::threadLauncher(void *(*threadfunc)(void*), void *argv)
 {
     void *result=0;
@@ -730,9 +663,95 @@ void Thread::threadLauncher(void *(*threadfunc)(void*), void *argv)
     errorHandler(UNEXPECTED);
 }
 
+#ifdef WITH_PROCESSES
+
+Thread *Thread::PKcreateUserspace(void *(*startfunc)(void *), void *argv,
+                    unsigned short options, pid_t pid)
+{
+    //Allocate memory for the thread, return if fail
+    unsigned int *base;
+    Thread *thread;
+    const int stackAlloc=(SYSTEM_MODE_PROCESS_STACK_SIZE+WATERMARK_LEN+
+        CTXSAVE_ON_STACK)/4;
+    //TODO: move to RAII
+    try {
+        base=new unsigned int[stackAlloc];
+    } catch(std::bad_alloc&)
+    {
+        errorHandler(OUT_OF_MEMORY);
+        return NULL;//Error
+    }
+    try {
+        thread=new Thread(base,SYSTEM_MODE_PROCESS_STACK_SIZE);
+    } catch(std::bad_alloc&)
+    {
+        delete[] base;
+        errorHandler(OUT_OF_MEMORY);
+        return NULL;//Error
+    }
+    try {
+        thread->userCtxsave=new unsigned int[CTXSAVE_SIZE];
+    } catch(std::bad_alloc&)
+    {
+        delete[] thread;
+        delete[] base;
+        errorHandler(OUT_OF_MEMORY);
+        return NULL;//Error
+    }
+
+    //Fill watermark and stack
+    memset(base, WATERMARK_FILL, WATERMARK_LEN);
+    base+=WATERMARK_LEN/sizeof(unsigned int);
+    memset(base, STACK_FILL, SYSTEM_MODE_PROCESS_STACK_SIZE);
+
+    //On some architectures some registers are saved on the stack, therefore
+    //initCtxsave *must* be called after filling the stack.
+    unsigned int *topOfStack=thread->watermark+stackAlloc;
+    miosix_private::initCtxsave(thread->ctxsave,startfunc,topOfStack,argv);
+    
+    thread->pid=pid;
+    if((options & JOINABLE)==0) thread->flags.IRQsetDetached();
+    
+    //Add thread to thread list
+    if(Scheduler::PKaddThread(thread,MAIN_PRIORITY)==false)
+    {
+        //Reached limit on number of threads
+        delete thread;
+        return NULL;
+    }
+    
+    return thread;
+}
+
+void Thread::setupUserspaceContext(unsigned int entry, unsigned int *gotBase,
+    unsigned int *stackTop)
+{
+    void *(*startfunc)(void*)=reinterpret_cast<void *(*)(void*)>(entry);
+    miosix_private::initCtxsave(cur->userCtxsave,startfunc,stackTop,0,gotBase);
+}
+
+miosix_private::SyscallParameters Thread::switchToUserspace()
+{
+    {
+        FastInterruptDisableLock dLock;
+        const_cast<Thread*>(cur)->flags.IRQsetUserspace(true);
+    }
+    Thread::yield(); //TODO: use a syscall to perform the continuation
+    if(const_cast<Thread*>(cur)->flags.isInUserspace()==true)
+        errorHandler(UNEXPECTED);
+    miosix_private::SyscallParameters result(cur->userCtxsave);
+    if(cur->pid==0) result.invalidate();
+    return result;
+}
+
+#endif //WITH_PROCESSES
+
 Thread::~Thread()
 {
-    if(flags.hasExternStack()==false) delete[] watermark;
+    delete[] watermark;
+    #ifdef WITH_PROCESSES
+    if(userCtxsave) delete[] userCtxsave;
+    #endif //WITH_PROCESSES
 }
 
 //
diff --git a/miosix/kernel/kernel.h b/miosix/kernel/kernel.h
index e746ccfe2a83bcc15c5c214fa34c3076ef661341..3f33bccc3ab8c51a8c77f6f7ef0a7f7b542071bd 100644
--- a/miosix/kernel/kernel.h
+++ b/miosix/kernel/kernel.h
@@ -693,10 +693,14 @@ public:
     static const int getStackSize();
     
     #ifdef WITH_PROCESSES
+
     /**
-     * \return the syscall parameters
+     * TODO: make private!
+     * Can only be called inside an IRQ, its use is to switch a userspace thread
+     * to kernelspace to perform a system call.
      */
-    static miosix_private::SyscallParameters getSyscallParameters();
+    static void IRQswitchToKernelspace();
+    
     #endif //WITH_PROCESSES
 	
 private:
@@ -710,46 +714,45 @@ private:
         /**
          * Constructor, sets flags to default.
          */
-        ThreadFlags(bool externStack=false) :
-                flags(externStack ? EXTERN_STACK : 0) {}
+        ThreadFlags() : flags(0) {}
 
         /**
          * Set the wait flag of the thread.
-         * Can only be called with interrupts enabled or within an interrupt.
+         * Can only be called with interrupts disabled or within an interrupt.
          * \param waiting if true the flag will be set, otherwise cleared
          */
         void IRQsetWait(bool waiting);
 
         /**
          * Set the wait_join flag of the thread.
-         * Can only be called with interrupts enabled or within an interrupt.
+         * Can only be called with interrupts disabled or within an interrupt.
          * \param waiting if true the flag will be set, otherwise cleared
          */
         void IRQsetJoinWait(bool waiting);
 
         /**
          * Set wait_cond flag of the thread.
-         * Can only be called with interrupts enabled or within an interrupt.
+         * Can only be called with interrupts disabled or within an interrupt.
          * \param waiting if true the flag will be set, otherwise cleared
          */
         void IRQsetCondWait(bool waiting);
 
         /**
          * Set the sleep flag of the thread.
-         * Can only be called with interrupts enabled or within an interrupt.
+         * Can only be called with interrupts disabled or within an interrupt.
          * \param sleeping if true the flag will be set, otherwise cleared
          */
         void IRQsetSleep(bool sleeping);
 
         /**
          * Set the deleted flag of the thread. This flag can't be cleared.
-         * Can only be called with interrupts enabled or within an interrupt.
+         * Can only be called with interrupts disabled or within an interrupt.
          */
         void IRQsetDeleted();
 
         /**
          * Set the sleep flag of the thread. This flag can't be cleared.
-         * Can only be called with interrupts enabled or within an interrupt.
+         * Can only be called with interrupts disabled or within an interrupt.
          */
         void IRQsetDeleting()
         {
@@ -758,12 +761,22 @@ private:
 
         /**
          * Set the detached flag. This flag can't be cleared.
-         * Can only be called with interrupts enabled or within an interrupt.
+         * Can only be called with interrupts disabled or within an interrupt.
          */
         void IRQsetDetached()
         {
             flags |= DETACHED;
         }
+        
+        /**
+         * Set the userspace flag of the thread.
+         * Can only be called with interrupts disabled or within an interrupt.
+         * \param sleeping if true the flag will be set, otherwise cleared
+         */
+        void IRQsetUserspace(bool userspace)
+        {
+            if(userspace) flags |= USERSPACE; else flags &= ~USERSPACE;
+        }
 
         /**
          * \return true if the wait flag is set
@@ -811,11 +824,6 @@ private:
          */
         bool isWaitingCond() const { return flags & WAIT_COND; }
         
-        /**
-         * \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 
@@ -847,31 +855,43 @@ private:
         ///\internal Thread is waiting on a condition variable
         static const unsigned int WAIT_COND=1<<6;
         
-        ///\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
     };
     
+    #ifdef WITH_PROCESSES
+
+    /**
+     * Create a thread to be used inside a process.
+     * Can only be called when the kernel is paused
+     * \param startfunc entry point
+     * \param argv parameter to be passed to the entry point
+     * \param options thread options
+     * \param pid process' pid
+     */
+    static Thread *PKcreateUserspace(void *(*startfunc)(void *),
+        void *argv, unsigned short options, pid_t pid);
+    
     /**
-     * 
-     * \param startfunc
-     * \param stacksize
-     * \param priority
-     * \param argv
-     * \param options
-     * \param gotBase
-     * \return 
+     * Setup the userspace context of the thread, so that it can be later
+     * switched to userspace. Must be called only once for each thread instance
+     * Can only be called when the kernel is paused
+     * \param entry userspace entry point
+     * \param gotBase base address of the GOT, also corresponding to the start
+     * of the RAM image of the process
+     * \param stackTop top of userspace stack
      */
-    static Thread *PKcreate(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);
+    static void setupUserspaceContext(unsigned int entry, unsigned int *gotBase,
+        unsigned int *stackTop);
+    
+    /**
+     * \return the syscall parameters
+     */
+    static miosix_private::SyscallParameters switchToUserspace();
+    
+    #endif //WITH_PROCESSES
 
     /**
      * Constructor, initializes thread data.
@@ -884,6 +904,10 @@ private:
         watermark(watermark), ctxsave(), stacksize(stacksize)
     {
         joinData.waitingForJoin=NULL;
+        #ifdef WITH_PROCESSES
+        pid=0;
+        userCtxsave=0;
+        #endif //WITH_PROCESSES
     }
 
     /**
@@ -951,8 +975,7 @@ private:
     friend void startKernel();
     //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);
     //Needs access to priority, savedPriority, mutexLocked and flags.
     friend class Mutex;
     //Needs access to flags
diff --git a/miosix/kernel/process.cpp b/miosix/kernel/process.cpp
index 554d9ba48999466374027857d2c51fa5436646e3..49f381031d8c1849c4eb54880910b38fee32f28d 100644
--- a/miosix/kernel/process.cpp
+++ b/miosix/kernel/process.cpp
@@ -26,6 +26,8 @@
  ***************************************************************************/
 
 #include <stdexcept>
+#include <memory>
+#include <cstdio>
 #include "process.h"
 
 using namespace std;
@@ -40,54 +42,95 @@ namespace miosix {
 
 Process *Process::create(const ElfProgram& program)
 {
-    //Loading the process outside the PKlock as relocation take time
-    Process *proc=new Process;
-    proc->image.load(program);
+    //Loading the process outside the PKlock as relocation takes time
+    auto_ptr<Process> proc(new Process(program));
     {
         PauseKernelLock dLock;
         pid_t pid=PKgetNewPid();
-        try {
-            processes[pid]=proc;
-        } catch(...) {
-            delete proc;
-            throw;
+        processes[pid]=proc.get();
+        Thread *thr=Thread::PKcreateUserspace(Process::start,0,
+            Thread::JOINABLE,pid);
+        if(thr==0)
+        {
+            processes.erase(pid);
+            throw runtime_error("Thread creation failed");
         }
-        Thread *thr=Thread::PKcreate(Process::start,
-            SYSTEM_MODE_PROCESS_STACK_SIZE,MAIN_PRIORITY,0,Thread::JOINABLE,pid,
-            program.getEntryPoint(),proc->image.getProcessBasePointer());
-        if(thr==0) throw runtime_error("Thread creation failed");
         //Cannot throw bad_alloc due to the reserve in Process's constructor.
         //This ensures we will never be in the uncomfortable situation where a
         //thread has already been created but there's no memory to list it
         //among the threads of a process
         proc->threads.push_back(thr);
     }
+    #ifdef SCHED_TYPE_EDF
+    //The new thread might have a closer deadline
+    if(isKernelRunning()) Thread::yield();
+    #endif //SCHED_TYPE_EDF
+    return proc.release(); //Do not delete the pointer
 }
 
-Process::Process()
+Process::Process(const ElfProgram& program) : program(program)
 {
     //This is required so that bad_alloc can never be thrown when the first
     //thread of the process will be stored in this vector
     threads.reserve(1);
+    //Done here so if not enough memory the new process is not even created
+    image.load(program);
 }
 
 void *Process::start(void *argv)
 {
-    //TODO
+    Thread *thr=Thread::getCurrentThread();
+    map<pid_t,Process*>::iterator it=processes.find(thr->pid);
+    if(it==processes.end()) errorHandler(UNEXPECTED);
+    Process *proc=it->second;
+    Thread::setupUserspaceContext(
+        proc->program.getEntryPoint(),proc->image.getProcessBasePointer(),
+        proc->image.getProcessBasePointer()+proc->image.getProcessImageSize());
+    bool running=true;
+    do {
+        miosix_private::SyscallParameters sp=Thread::switchToUserspace();
+        if(sp.isValid())
+        {
+            switch(sp.getSyscallId())
+            {
+                case 1:
+                    iprintf("Exit %d\n",sp.getFirstParameter());
+                    running=false;
+                    break;
+                case 2:
+                    //FIXME: check that the pointer belongs to the process
+                    sp.setReturnValue(write(sp.getFirstParameter(),
+                        reinterpret_cast<const char*>(sp.getSecondParameter()),
+                        sp.getThirdParameter()));
+                    break;
+                default:
+                    iprintf("Unexpected invalid syscall\n");
+                    running=false;
+                    break;
+            }
+        }
+        if(Thread::testTerminate())
+        {
+            running=false;
+        }
+    } while(running);
+    //TODO: handle process termination
+    return 0;
 }
 
 pid_t Process::PKgetNewPid()
 {
     for(;;pidCounter++)
     {
+        if(pidCounter<0) pidCounter=1;
         if(pidCounter==0) continue; //Zero is not a valid pid
-        map<pid_t,Process *>::iterator it=processes.find(pidCounter);
+        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;
+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 0c70b7e49ce0d55a9a0964d9c0a17ece55374f3a..51b9fe16da8a332d557e40e0bb8661cf84adefbc 100644
--- a/miosix/kernel/process.h
+++ b/miosix/kernel/process.h
@@ -39,23 +39,46 @@
 
 namespace miosix {
 
+/**
+ * Process class, allows to create and handle processes
+ */
 class Process
 {
 public:
-    
+    /**
+     * Create a new process
+     * \param program Program that the process will execute
+     * \return a pointer to the newly created process
+     * \throws std::exception or a subclass in case of errors, including
+     * not emough memory to spawn the process
+     */
     static Process *create(const ElfProgram& program);
     
 private:
+    Process(const Process&);
+    Process& operator= (const Process&);
     
-    Process();
+    /**
+     * Constructor
+     * \param program program that will be executed by the process
+     */
+    Process(const ElfProgram& program);
     
+    /**
+     * Contains the process' main loop. 
+     * \param argv ignored parameter
+     * \return null
+     */
     static void *start(void *argv);
     
+    /**
+     * \return an unique pid that is not zero and is not already in use in the
+     * system, used to assign a pid to a new process.<br>
+     * Must be called when the kernel is paused to avoid race conditions.
+     */
     static pid_t PKgetNewPid();
     
-    Process(const Process&);
-    Process& operator= (const Process&);
-    
+    ElfProgram program; ///<The program that is running inside the process
     ProcessImage image; ///<The RAM image of a process
     std::vector<Thread *> threads; ///<Threads that belong to the process
     
diff --git a/miosix/kernel/scheduler/control/control_scheduler.cpp b/miosix/kernel/scheduler/control/control_scheduler.cpp
index 9effc279f8454a93a039245171f64b3f6270730b..e909985099bdcea0641eec30ceee44c36dd56e66 100644
--- a/miosix/kernel/scheduler/control/control_scheduler.cpp
+++ b/miosix/kernel/scheduler/control/control_scheduler.cpp
@@ -209,7 +209,13 @@ void ControlScheduler::IRQfindNextThread()
         {
             //Found a READY thread, so run this one
             cur=curInRound;
-            ctxsave=cur->ctxsave;
+            #ifdef WITH_PROCESSES
+            if(const_cast<Thread*>(cur)->flags.isInUserspace()==false)
+                ctxsave=temp->ctxsave;
+            else ctxsave=temp->userCtxsave;
+            #else //WITH_PROCESSES
+            ctxsave=temp->ctxsave;
+            #endif //WITH_PROCESSES
             miosix_private::AuxiliaryTimer::IRQsetValue(
                     curInRound->schedData.bo/multFactor);
             return;
diff --git a/miosix/kernel/scheduler/edf/edf_scheduler.cpp b/miosix/kernel/scheduler/edf/edf_scheduler.cpp
index d115a44d34bd559b275c5234c7e4a0d450f49e4d..af6a4f56477f07ed2e579cdeb89cfafb114643cf 100644
--- a/miosix/kernel/scheduler/edf/edf_scheduler.cpp
+++ b/miosix/kernel/scheduler/edf/edf_scheduler.cpp
@@ -111,7 +111,13 @@ void EDFScheduler::IRQfindNextThread()
         if(walk->flags.isReady())
         {
             cur=walk;
-            ctxsave=cur->ctxsave;
+            #ifdef WITH_PROCESSES
+            if(const_cast<Thread*>(cur)->flags.isInUserspace()==false)
+                ctxsave=temp->ctxsave;
+            else ctxsave=temp->userCtxsave;
+            #else //WITH_PROCESSES
+            ctxsave=temp->ctxsave;
+            #endif //WITH_PROCESSES
             return;
         }
         walk=walk->schedData.next;
diff --git a/miosix/kernel/scheduler/priority/priority_scheduler.cpp b/miosix/kernel/scheduler/priority/priority_scheduler.cpp
index da6eddae94578087900a71c290d0b1df947c9050..8f39ab965491f94b5d91615b597296a669d3a266 100644
--- a/miosix/kernel/scheduler/priority/priority_scheduler.cpp
+++ b/miosix/kernel/scheduler/priority/priority_scheduler.cpp
@@ -200,7 +200,13 @@ void PriorityScheduler::IRQfindNextThread()
             {
                 //Found a READY thread, so run this one
                 cur=temp;
+                #ifdef WITH_PROCESSES
+                if(const_cast<Thread*>(cur)->flags.isInUserspace()==false)
+                    ctxsave=temp->ctxsave;
+                else ctxsave=temp->userCtxsave;
+                #else //WITH_PROCESSES
                 ctxsave=temp->ctxsave;
+                #endif //WITH_PROCESSES
                 //Rotate to next thread so that next time the list is walked
                 //a different thread, if available, will be chosen first
                 thread_list[i]=temp;