LOGIN   :::   RECOVER PASS   :::   GET ACCOUNT    
Browse
  • Projects
  • Code (CVS)
  • Forums
  • News
  • Articles
  • Polls
  •  
    OpenCores
  • FAQ
  • CVS HowTo
  • Mission
  • Media
  • Tools
  • Advertise
  • Mirrors
  • Logos
  • Contact us
  • Find Resources
  • Job Opportunity
  •  
    Tools
  • Search
      
  • Download Cores (CVSGet)
  •  
    More
  • Wishbone
  • Perlilog
  • EDA tools
  • OpenTech CD
  •  
    Navigation: All forums > Cvs-checkins > Message List > Message Post

    Message

    Reply | Reply all
    Date Prev | Date Next | Thread Prev | Thread Next Date Index | Thread Index

    From: cvs at opencores.org<cvs@o...>
    Date: Thu Sep 14 07:07:52 CEST 2006
    Subject: [cvs-checkins] MODIFIED: mlite ...
    Top
    Date: 00/06/09 14:07:07

    Modified: mlite/kernel rtos.c
    Log:
    Improved multi-cpu support


    Revision Changes Path
    1.6 mlite/kernel/rtos.c

    http://www.opencores.org/cvsweb.shtml/mlite/kernel/rtos.c.diff?r1=1.5&r2=1.6

    (In the diff below, changes in quantity of whitespace are not shown.)

    Index: rtos.c
    ===================================================================
    RCS file: /cvsroot/rhoads/mlite/kernel/rtos.c,v
    retrieving revision 1.5
    retrieving revision 1.6
    diff -u -b -r1.5 -r1.6
    --- rtos.c 11 Sep 2006 01:39:19 -0000 1.5
    +++ rtos.c 14 Sep 2006 05:07:52 -0000 1.6
    @@ -53,7 +53,7 @@
    //typedef struct OS_Heap_s OS_Heap_t;

    typedef enum {
    - THREAD_BLOCKED = 0,
    + THREAD_PEND = 0,
    THREAD_READY = 1,
    THREAD_RUNNING = 2
    } OS_ThreadState_e;
    @@ -304,7 +304,7 @@
    thread->next->prev = thread->prev;
    thread->next = NULL;
    thread->prev = NULL;
    - thread->state = THREAD_BLOCKED;
    + thread->state = THREAD_PEND;
    }


    @@ -361,13 +361,13 @@
    }


    +#if OS_CPU_COUNT <= 1
    /******************************************/
    //Loads a new thread
    //Must be called with interrupts disabled
    static void OS_ThreadReschedule(int RoundRobin)
    {
    - OS_Thread_t *threadNext, *threadCurrent, *threadBest, *threadTry;
    - uint32 cpuIndex = OS_CpuIndex();
    + OS_Thread_t *threadNext, *threadCurrent, *threadTry;
    int rc;

    if(ThreadSwapEnabled == 0 || InterruptInside)
    @@ -377,30 +377,133 @@
    }

    //Determine which thread should run
    - threadCurrent = ThreadCurrent[cpuIndex];
    + threadCurrent = ThreadCurrent[0];
    threadNext = threadCurrent;
    + if(threadCurrent == NULL || threadCurrent->state == THREAD_PEND)
    + threadNext = ThreadHead;
    + else if(threadCurrent->priority < ThreadHead->priority)
    + threadNext = ThreadHead;
    + else if(RoundRobin)
    + {
    + //Determine next ready thread with same priority
    + threadTry = threadCurrent->next;
    + if(threadTry && threadTry->priority == threadCurrent->priority)
    + threadNext = threadTry;
    + else
    + threadNext = ThreadHead;
    + }
    +
    + if(threadNext != threadCurrent)
    + {
    + //Swap threads
    + ThreadCurrent[0] = threadNext;
    + assert(threadNext);
    + if(threadCurrent)
    + {
    + assert(threadCurrent->magic[0] == THREAD_MAGIC); //check stack overflow
    + //printf("OS_ThreadRescheduleSave(%s)\n", threadPrev->name);
    + rc = setjmp(threadCurrent->env); //ANSI C call to save registers
    + if(rc)
    + {
    + //Returned from longjmp()
    + return;
    + }
    + }
    +
    + threadNext = ThreadCurrent[0]; //removed warning
    + //printf("OS_ThreadRescheduleRestore(%s)\n", threadNext->name);
    + longjmp(threadNext->env, 1); //ANSI C call to restore registers
    + }
    +}
    +
    +#else //#if OS_CPU_COUNT <= 1
    +
    +/******************************************/ +//Loads a new thread in a multiprocessor environment +//Must be called with interrupts disabled +static void OS_ThreadReschedule(int RoundRobin) +{ + OS_Thread_t *threadNext, *threadCurrent, *threadBest, *threadAlt; + uint32 i, cpuLow, priorityLow, cpuIndex = OS_CpuIndex(); + int rc; + static volatile int CpuReschedule; //remove warning + + if(ThreadSwapEnabled == 0 || InterruptInside) + { + ThreadNeedReschedule |= 2 + RoundRobin; + return; + } + + //Find which CPU is running the lowest priority thread + CpuReschedule = -1; + cpuLow = 0; + priorityLow = 0xffffffff; + for(i = 0; i < OS_CPU_COUNT; ++i) + { + if(i != cpuIndex && (ThreadCurrent[i] == NULL || + ThreadCurrent[i]->priority < priorityLow)) + { + cpuLow = i; + if(ThreadCurrent[i]) + priorityLow = ThreadCurrent[i]->priority; + else + priorityLow = 0; + } + } + + //Determine highest priority ready threads for(threadBest = ThreadHead; threadBest; threadBest = threadBest->next) { if(threadBest->state == THREAD_READY) break; } - if(threadBest == NULL && threadCurrent && threadCurrent->state == THREAD_RUNNING) - threadBest = threadCurrent; - assert(threadBest); - if(threadCurrent == NULL || threadCurrent->state == THREAD_BLOCKED) + threadAlt = NULL; + if(threadBest) + { + for(threadAlt = threadBest->next; threadAlt; threadAlt = threadAlt->next) + { + if(threadAlt->state == THREAD_READY) + break; + } + } + + //Determine if a CPU needs to reschedule + if(threadAlt && threadAlt->priority > priorityLow) + CpuReschedule = cpuLow; + + //Determine which thread should run + threadCurrent = ThreadCurrent[cpuIndex]; + threadNext = threadCurrent; + if(threadCurrent == NULL || threadCurrent->state == THREAD_PEND) + { threadNext = threadBest; - else if(threadCurrent->priority < threadBest->priority) + } + else if(threadBest && threadCurrent->priority < threadBest->priority) + { threadNext = threadBest; + + if(threadAlt == NULL || threadCurrent->priority > threadAlt->priority) + { + CpuReschedule = cpuLow; + + //Only enable this if there really are multiple CPUs + //Try to minimize thread swapping by detecting if the other + //CPU would just start running threadCurrent +// if(threadCurrent->priority > priorityLow) +// threadNext = threadCurrent; + } + } else if(RoundRobin) { - for(threadTry = threadCurrent->next; threadTry; threadTry = threadTry->next) + //Find the next ready thread + for(threadAlt = threadCurrent->next; threadAlt; threadAlt = threadAlt->next) { - if(threadTry->state == THREAD_READY) + if(threadAlt->state == THREAD_READY) break; } - if(threadTry && threadTry->priority == threadCurrent->priority) - threadNext = threadTry; - else if(threadBest->priority == threadCurrent->priority) + if(threadAlt && threadAlt->priority == threadCurrent->priority) + threadNext = threadAlt; + else if(threadBest && threadBest->priority >= threadCurrent->priority) threadNext = threadBest; } @@ -420,19 +523,29 @@ if(rc) { //Returned from longjmp() + if(CpuReschedule >= 0) + OS_CpuInterrupt(CpuReschedule, 1); return; } } + //Restore spin lock count cpuIndex = OS_CpuIndex(); //removed warning threadNext = ThreadCurrent[cpuIndex]; //removed warning - //printf("OS_ThreadRescheduleRestore(%s)\n", threadNext->name); threadNext->state = THREAD_RUNNING; OS_SpinLockSet(threadNext->spinLocks); + + //printf("OS_ThreadRescheduleRestore(%s)\n", threadNext->name); longjmp(threadNext->env, 1); //ANSI C call to restore registers } + + //Check if a different CPU needs to swap threads + if(CpuReschedule >= 0) + OS_CpuInterrupt(CpuReschedule, 1); } +#endif //#if OS_CPU_COUNT <= 1 + /******************************************/ static void OS_ThreadInit(void *Arg) @@ -578,7 +691,7 @@ uint32 state; state = OS_CriticalBegin(); Thread->priority = Priority; - if(Thread->state != THREAD_BLOCKED) + if(Thread->state != THREAD_PEND) { OS_ThreadPriorityRemove(&ThreadHead, Thread); OS_ThreadPriorityInsert(&ThreadHead, Thread); @@ -1257,6 +1370,25 @@ SpinLockArray[cpuIndex] = (uint8)count; assert(count); } + + +/******************************************/ +void OS_CpuInterrupt(uint32 cpuIndex, uint32 bitfield) +{ + (void)cpuIndex; + (void)bitfield; +} + + +/******************************************/ +void OS_CpuInterruptServiceRoutine(void *Arg) +{ + uint32 state; + (void)Arg; + state = OS_SpinLock(); + OS_ThreadReschedule(0); + OS_SpinUnlock(state); +} #endif

     
    Copyright (c) 1999 OPENCORES.ORG. All rights reserved.