Example #1
0
        public static void StackFree(tThread *pThread, void *pAddr)
        {
            tThreadStack *pStack = pThread->pThreadStack;

        #if _DEBUG
            ((uint *)pAddr)--;
            Mem.memset(pAddr, 0xfe, pStack->ofs - (uint)(((byte *)pAddr) - pStack->memory));
        #endif
            pStack->ofs = (uint)(((byte *)pAddr) - pStack->memory);
        }
Example #2
0
        static void Delete(tThread *pThis)
        {
            tThreadStack *pStack = pThis->pThreadStack;

            while (pStack != null)
            {
                tThreadStack *pNextStack = pStack->pNext;
                Mem.free(pStack);
                pStack = pNextStack;
            }
            Heap.MakeDeletable((/*HEAP_PTR*/ byte *)pThis);
        }
Example #3
0
        public static tMethodState *Direct(tThread *pThread, tMD_MethodDef *pMethod, tMethodState *pCaller, uint isInternalNewObjCall)
        {
            tMethodState *pThis;

            Mem.heapcheck();

            if (pMethod->isFilled == 0)
            {
                tMD_TypeDef *pTypeDef;

                pTypeDef = MetaData.GetTypeDefFromMethodDef(pMethod);
                MetaData.Fill_TypeDef(pTypeDef, null, null);
            }

            pThis = (tMethodState *)Thread.StackAlloc(pThread, (uint)sizeof(tMethodState));
            pThis->finalizerThis = null;
            pThis->pCaller       = pCaller;
            pThis->pMetaData     = pMethod->pMetaData;
            pThis->pMethod       = pMethod;
            if (pMethod->pJITted == null)
            {
                // If method has not already been JITted
                JIT.Prepare(pMethod, 0);
            }
            pThis->pJIT                 = pMethod->pJITted;
            pThis->ipOffset             = 0;
            pThis->pEvalStack           = (byte *)Thread.StackAlloc(pThread, pThis->pMethod->pJITted->maxStack);
            pThis->stackOfs             = 0;
            pThis->isInternalNewObjCall = isInternalNewObjCall;
            pThis->pNextDelegate        = null;
            pThis->pDelegateParams      = null;

            pThis->pParamsLocals = (byte *)Thread.StackAlloc(pThread, pMethod->parameterStackSize + pMethod->pJITted->localsStackSize);
            Mem.memset(pThis->pParamsLocals, 0, pMethod->parameterStackSize + pMethod->pJITted->localsStackSize);

#if DIAG_METHOD_CALLS
            // Keep track of the number of times this method is called
            pMethod->callCount++;
            pThis->startTime = microTime();
#endif

            Mem.heapcheck();

            return(pThis);
        }
Example #4
0
        public static tThread *New()
        {
            tThread *pThis;

            // Create thread and initial method state. This is allocated on the managed heap, and
            // mark as undeletable. When the thread exits, it was marked as deletable.
            pThis = (tThread *)Heap.AllocType(Type.types[Type.TYPE_SYSTEM_THREADING_THREAD]);
            Heap.MakeUndeletable((/*HEAP_PTR*/ byte *)pThis);
            Mem.memset(pThis, 0, (SIZE_T)sizeof(tThread));
            pThis->threadID = ++threadID;

            Reset(pThis);

            // Add to list of all thread
            pThis->pNextThread = pAllThreads;
            pAllThreads        = pThis;

            return(pThis);
        }
Example #5
0
        // Returns 1 if all is OK
        // Returns 0 if the wrong thread is releasing the sync, or if no thread hold the sync
        public static uint SyncExit(/*HEAP_PTR*/ byte *obj)
        {
            tHeapEntry *pHeapEntry = GET_HEAPENTRY(obj);
            tThread *   pThread    = Thread.GetCurrent();

            if (pHeapEntry->pSync == null)
            {
                return(0);
            }
            if (pHeapEntry->pSync->pThread != pThread)
            {
                return(0);
            }
            if (--pHeapEntry->pSync->count == 0)
            {
                DeleteSync(pHeapEntry);
            }
            return(1);
        }
Example #6
0
        static void Reset(tThread *pThis)
        {
            pThis->pCurrentMethodState    = null;
            pThis->threadExitValue        = 0;
            pThis->nextFinallyUnwindStack = 0;
            pThis->pAsync   = null;
            pThis->hasParam = 0;

            pThis->startDelegate = null;
            pThis->param         = null;
            pThis->state         = THREADSTATE_UNSTARTED;

            // Allocate the first chunk of thread-local stack
            if (pThis->pThreadStack == null)
            {
                pThis->pThreadStack        = ((tThreadStack *)Mem.malloc((SIZE_T)sizeof(tThreadStack)));
                pThis->pThreadStack->pNext = null;
            }
            pThis->pThreadStack->ofs = 0;
        }
Example #7
0
        // Return 1 if lock succesfully got
        // Return 0 if couldn't get the lock this time
        public static uint SyncTryEnter(/*HEAP_PTR*/ byte *obj)
        {
            tHeapEntry *pHeapEntry = GET_HEAPENTRY(obj);
            tThread *   pThread    = Thread.GetCurrent();
            tSync *     pSync;

            pSync = EnsureSync(pHeapEntry);
            if (pSync->pThread == null)
            {
                pSync->pThread = pThread;
                pSync->count   = 1;
                return(1);
            }
            if (pSync->pThread == pThread)
            {
                pSync->count++;
                return(1);
            }
            return(0);
        }
Example #8
0
        public static void *StackAlloc(tThread *pThread, uint size)
        {
            tThreadStack *pStack = pThread->pThreadStack;
            void *        pAddr  = pStack->memory + pStack->ofs;

        #if _DEBUG
            *(uint *)pAddr = 0xabababab;
            ((uint *)pAddr)++;
            pStack->ofs += 4;
        #endif
            pStack->ofs += size;
            if (pStack->ofs > tThreadStack.THREADSTACK_CHUNK_SIZE)
            {
                Sys.Crash("Thread-local stack is too large");
            }
        #if _DEBUG
            Mem.memset(pAddr, 0xcd, size);
            *(uint *)(((byte *)pAddr) + size) = 0xfbfbfbfb;
            pStack->ofs += 4;
        #endif
            return(pAddr);
        }
Example #9
0
        public static uint Update(uint maxInstr, int *pReturnCode)
        {
            tThread *pThread;
            tThread *pPrevThread;
            uint     status;

            pThread = pAllThreads;
            // Set the initial thread to the RUNNING state.
            pThread->state = THREADSTATE_RUNNING;
            // Set the initial CurrentThread
            pCurrentThread = pThread;

            for (;;)
            {
                uint minSleepTime = 0xffffffff;
                int  threadExitValue;

                status = JIT_Execute.Execute(pThread, maxInstr);
                switch (status)
                {
                case Thread.THREAD_STATUS_EXIT:
                    threadExitValue = pThread->threadExitValue;
                    Sys.log_f(1, "Thread ID#%d exited. Return value: %d\n", (int)pThread->threadID, (int)threadExitValue);
                    // Remove the current thread from the running threads list.
                    // Note that this list may have changed since before the call to JitOps.JIT_Execute().
                    {
                        if (pAllThreads == pThread)
                        {
                            pAllThreads = pAllThreads->pNextThread;
                        }
                        else
                        {
                            tThread *pThread1 = pAllThreads;
                            while (pThread1->pNextThread != pThread)
                            {
                                pThread1 = pThread1->pNextThread;
                            }
                            pThread1->pNextThread = pThread1->pNextThread->pNextThread;
                        }
                    }
                    // Delete the current thread
                    Thread.Delete(pThread);
                    // If there are no more threads left running, then exit application (by returning)
                    // Threads that are unstarted or background do not stop the exit
                    // [Steve edit] Threads that are suspended also do not stop the exit. This is because you'd just
                    // wait forever for them if they did. Note that 'exit' doesn't mean tearing down the process
                    // like in a regular .NET runtime case. The application state is still there and we can make
                    // further calls into it to create new threads.
                    {
                        tThread *pThread2 = pAllThreads;
                        uint     canExit  = 1;
                        while (pThread2 != null)
                        {
                            if (
                                ((pThread2->state & THREADSTATE_BACKGROUND) == 0) &&
                                ((pThread2->state & (~THREADSTATE_BACKGROUND)) != THREADSTATE_UNSTARTED) &&
                                ((pThread2->state & (~THREADSTATE_BACKGROUND)) != THREADSTATE_SUSPENDED))
                            {
                                canExit = 0;
                                break;
                            }
                            pThread2 = pThread2->pNextThread;
                        }
                        if (canExit != 0)
                        {
                            if (pReturnCode != null)
                            {
                                *pReturnCode = threadExitValue;
                            }
                            return(THREADSTATE_STOPPED);
                        }
                    }
                    pThread = pAllThreads;     // This is not really correct, but it'll work for the time being
                    break;

                case THREAD_STATUS_RUNNING:
                case THREAD_STATUS_LOCK_EXIT:
                    // Nothing to do
                    break;

                case THREAD_STATUS_ASYNC:
                    pThread->pAsync->startTime = Sys.msTime();
                    break;
                }

                // Move on to the next thread.
                // Find the next thread that isn't sleeping or blocked on IO
                pPrevThread = pThread;
                for (;;)
                {
                    pThread = pThread->pNextThread;
                    if (pThread == null)
                    {
                        // That was the thread -- return!
                        return(THREADSTATE_RUNNING);
                    }
                    // Set the CurrentThread correctly
                    pCurrentThread = pThread;
                    if ((pThread->state & (~THREADSTATE_BACKGROUND)) != 0)
                    {
                        // Thread is not running
                        continue;
                    }
                    if (pThread->pAsync != null)
                    {
                        // Discover if whatever is being waited for is finished
                        tAsyncCall *pAsync = pThread->pAsync;
                        if (pAsync->sleepTime >= 0)
                        {
                            // This is a sleep
                            ulong nowTime          = Sys.msTime();
                            int   msSleepRemaining = pAsync->sleepTime - (int)(nowTime - pAsync->startTime);
                            if (msSleepRemaining <= 0)
                            {
                                // Sleep is finished
                                break;
                            }
                            // Sleep is not finished, so continue to next thread
                            if ((uint)msSleepRemaining < minSleepTime)
                            {
                                minSleepTime = (uint)msSleepRemaining;
                            }
                        }
                        else
                        {
                            // This is blocking IO, or a lock
                            tMethodState *pMethodState = pThread->pCurrentMethodState;
                            byte *        pThis;
                            uint          thisOfs;
                            uint          unblocked;

                            if (MetaData.METHOD_ISSTATIC(pMethodState->pMethod))
                            {
                                pThis   = null;
                                thisOfs = 0;
                            }
                            else
                            {
                                pThis   = *(byte **)pMethodState->pParamsLocals;
                                thisOfs = 4;
                            }
                            unblocked = ((fnInternalCallCheck)H.ToObj(pAsync->checkFn))(null, pThis, pMethodState->pParamsLocals + thisOfs, pMethodState->pEvalStack, pAsync);
                            if (unblocked != 0)
                            {
                                // The IO has unblocked, and the return value is ready.
                                // So delete the async object.
                                // TODO: The async->state object needs to be deleted somehow (maybe)
                                Mem.free(pAsync);
                                // And remove it from the thread
                                pThread->pAsync = null;
                                break;
                            }
                            minSleepTime = 5;
                        }
                    }
                    else
                    {
                        // Thread is ready to run
                        break;
                    }
                    if (pThread == pPrevThread)
                    {
                        // When it gets here, it means that all threads are currently blocked.
                        //printf("All blocked; sleep(%d)\n", minSleepTime);
                        Sys.SleepMS(minSleepTime);
                    }
                }
            }
        }