⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcmb_smp.c

📁 eCos操作系统源码
💻 C
📖 第 1 页 / 共 3 页
字号:
{    HAL_SMP_CPU_TYPE cpu;//    PC_WRITE_SCREEN( PC_SCREEN_LINE(2)+0, '!' );#ifndef CYG_HAL_STARTUP_RAM     // Wait for INIT interrupt to be deasserted    while( !init_deasserted )        continue;#endif    //    PC_WRITE_SCREEN( PC_SCREEN_LINE(2)+1, '!' );        cpu  = HAL_SMP_CPU_THIS();    //    PC_WRITE_SCREEN_8( PC_SCREEN_LINE(2)+6, cpu );    #ifndef CYG_HAL_STARTUP_RAM     // Wait 1s for the world to settle    hal_delay_us( 1000000 );//    PC_WRITE_SCREEN( PC_SCREEN_LINE(2)+2, '!' );             // Setup our APIC    cyg_hal_smp_init_apic();#endif    //    PC_WRITE_SCREEN( PC_SCREEN_LINE(2)+3, '!' );        #ifdef CYGPKG_KERNEL_SMP_SUPPORT			    cyg_hal_smp_cpu_running[cpu] = 1;    cyg_kernel_smp_startup();#else     for(;;)    {        void (*entry)(void);        while( (entry = cyg_hal_smp_cpu_entry[cpu]) == 0 )        {#if 0 //SCREEN_DIAGNOSTICS                            static int n;            PC_WRITE_SCREEN_8( PC_SCREEN_LINE(2)+10, n );            PC_WRITE_SCREEN_8( PC_SCREEN_LINE(2)+15, cyg_hal_smp_cpu_sync[cpu] );            PC_WRITE_SCREEN_8( PC_SCREEN_LINE(2)+30, cyg_hal_smp_cpu_sync_flag[0] );            PC_WRITE_SCREEN_8( PC_SCREEN_LINE(2)+35, cyg_hal_smp_cpu_sync_flag[1] );            PC_WRITE_SCREEN_8( PC_SCREEN_LINE(2)+40, cyg_hal_smp_vsr_sync_flag );            n++;#endif            hal_delay_us( 100 );                    }//        PC_WRITE_SCREEN( PC_SCREEN_LINE(2)+4, '!' );        cyg_hal_smp_cpu_entry[cpu] = 0;  //        PC_WRITE_SCREEN_32( PC_SCREEN_LINE(2)+20, entry );           if( entry != NULL )        {            cyg_hal_smp_cpu_running[cpu] = 1;            entry();        }    }#endif     }/*------------------------------------------------------------------------*/__externC void cyg_hal_smp_init(void){    if( !cyg_hal_find_smp_config() )        return;    if( !cyg_hal_parse_smp_config() )        return;    if( !cyg_hal_smp_init_apic() )        return;    if( !cyg_hal_smp_init_ioapic() )        return;}/*------------------------------------------------------------------------*/__externC void cyg_hal_smp_cpu_start_all(void){    HAL_SMP_CPU_TYPE cpu;    for( cpu = 0; cpu < HAL_SMP_CPU_COUNT(); cpu++ )    {        cyg_hal_smp_cpu_sync[cpu] = 0;        cyg_hal_smp_cpu_sync_flag[cpu] = 0;        cyg_hal_smp_cpu_running[cpu] = 0;        cyg_hal_smp_cpu_entry[cpu] = 0;                if( cpu != HAL_SMP_CPU_THIS() )            cyg_hal_cpu_start( cpu );        else cyg_hal_smp_cpu_running[cpu] = 1;    }}/*------------------------------------------------------------------------*/// SMP message buffers.// SMP CPUs pass messages to eachother via a small circular buffer// protected by a spinlock. Each message is a single 32 bit word with// a type code in the top 4 bits and any argument in the remaining// 28 bits.#define SMP_MSGBUF_SIZE 4static struct smp_msg_t{    HAL_SPINLOCK_TYPE           lock;           // protecting spinlock    volatile CYG_WORD32         msgs[SMP_MSGBUF_SIZE]; // message buffer    volatile CYG_WORD32         head;           // head of list    volatile CYG_WORD32         tail;           // tail of list    volatile CYG_WORD32         reschedule;     // reschedule request    volatile CYG_WORD32         timeslice;      // timeslice request} smp_msg[HAL_SMP_CPU_MAX];/*------------------------------------------------------------------------*/// Pass a message to another CPU.#if SCREEN_DIAGNOSTICSstatic int res_msgs[2], tms_msgs[2];#endif__externC void cyg_hal_cpu_message( HAL_SMP_CPU_TYPE cpu,                                    CYG_WORD32 msg,                                    CYG_WORD32 arg,                                    CYG_WORD32 wait){#if 1    CYG_INTERRUPT_STATE istate;        struct smp_msg_t *m = &smp_msg[cpu];    int i;    HAL_SMP_CPU_TYPE me = HAL_SMP_CPU_THIS();     HAL_DISABLE_INTERRUPTS( istate );        // Get access to the message buffer for the selected CPU    HAL_SPINLOCK_SPIN( m->lock );#if 0 //SCREEN_DIAGNOSTICS        if( msg == HAL_SMP_MESSAGE_RESCHEDULE )        res_msgs[me]++;    else if( msg == HAL_SMP_MESSAGE_TIMESLICE )        tms_msgs[me]++;    PC_WRITE_SCREEN_8( PC_SCREEN_LINE(18+me), me);         PC_WRITE_SCREEN_16( PC_SCREEN_LINE(18+me)+40, res_msgs[me]);     PC_WRITE_SCREEN_16( PC_SCREEN_LINE(18+me)+45, tms_msgs[me]); #endif     if( msg == HAL_SMP_MESSAGE_RESCHEDULE )        m->reschedule = true;    else if( msg == HAL_SMP_MESSAGE_TIMESLICE )        m->timeslice = true;    else    {        CYG_WORD32 next = (m->tail + 1) & (SMP_MSGBUF_SIZE-1);        // If the buffer is full, wait for space to appear in it.        // This should only need to be done very rarely.            while( next == m->head )        {            HAL_SPINLOCK_CLEAR( m->lock );            for( i = 0; i < 1000; i++ );            HAL_SPINLOCK_SPIN( m->lock );                }        m->msgs[m->tail] = msg | arg;        m->tail = next;    }        // Now send an interrupt to the CPU.    //    PC_WRITE_SCREEN_16( PC_SCREEN_LINE(18+me)+50, cyg_hal_smp_cpu_running[cpu] );        if( cyg_hal_smp_cpu_running[cpu] )    {        CYG_WORD32 icrlo, icrhi;        // Set the ICR fields we want to write. Most fields are zero        // except the destination in the high word and the vector        // number in the low.        icrhi = cpu<<24;        icrlo = CYGNUM_HAL_SMP_CPU_INTERRUPT_VECTOR( cpu );        // Write the ICR register. The interrupt will be raised when        // the low word is written.        HAL_APIC_WRITE( HAL_APIC_ICR_HI, icrhi );        HAL_APIC_WRITE( HAL_APIC_ICR_LO, icrlo );        // Wait for the ICR to become inactive        do {#if 0 //SCREEN_DIAGNOSTICS                        static int n;                            PC_WRITE_SCREEN_8( PC_SCREEN_LINE(18+me)+55, n );            n++;#endif                        HAL_APIC_READ( HAL_APIC_ICR_LO, icrlo );        } while( (icrlo & 0x00001000) != 0 );            }    HAL_SPINLOCK_CLEAR( m->lock );    // If we are expected to wait for the command to complete, then    // spin here until it does. We actually wait for the destination    // CPU to empty its input buffer. So we might wait for messages    // from other CPUs as well. But this is benign.        while(wait)    {        for( i = 0; i < 1000; i++ );                HAL_SPINLOCK_SPIN( m->lock );        if( m->head == m->tail )            wait = false;                HAL_SPINLOCK_CLEAR( m->lock );    }     HAL_RESTORE_INTERRUPTS( istate );#endif    }/*------------------------------------------------------------------------*/#if SCREEN_DIAGNOSTICSstatic int isrs[2];static int dsrs[2];#endif__externC CYG_WORD32 cyg_hal_cpu_message_isr( CYG_WORD32 vector, CYG_ADDRWORD data ){    HAL_SMP_CPU_TYPE me = HAL_SMP_CPU_THIS();    struct smp_msg_t *m = &smp_msg[me];    CYG_WORD32 ret = 1;    CYG_INTERRUPT_STATE istate;        HAL_DISABLE_INTERRUPTS( istate );    HAL_SPINLOCK_SPIN( m->lock );    // First, acknowledge the interrupt.        HAL_INTERRUPT_ACKNOWLEDGE( vector );#if SCREEN_DIAGNOSTICS    isrs[me]++;        PC_WRITE_SCREEN_8( PC_SCREEN_LINE(18+me), me);     PC_WRITE_SCREEN_16( PC_SCREEN_LINE(18+me)+5, isrs[me]); #endif        if( m->reschedule || m->timeslice )        ret |= 2;               // Ask for the DSR to be called.        // Now pick messages out of the buffer and handle them        while( m->head != m->tail )    {        CYG_WORD32 msg = m->msgs[m->head];        switch( msg & HAL_SMP_MESSAGE_TYPE )        {        case HAL_SMP_MESSAGE_RESCHEDULE:            ret |= 2;           // Ask for the DSR to be called.            break;        case HAL_SMP_MESSAGE_MASK:            // Mask the supplied vector//            cyg_hal_interrupt_set_mask( msg&HAL_SMP_MESSAGE_ARG, false );            break;        case HAL_SMP_MESSAGE_UNMASK:            // Unmask the supplied vector//            cyg_hal_interrupt_set_mask( msg&HAL_SMP_MESSAGE_ARG, true );            break;        case HAL_SMP_MESSAGE_REVECTOR:            // Deal with a change of CPU assignment for a vector. We            // only actually worry about what happens when the vector            // is changed to some other CPU. We just mask the            // interrupt locally.//            if( hal_interrupt_cpu[msg&HAL_SMP_MESSAGE_ARG] != me )//                cyg_hal_interrupt_set_mask( msg&HAL_SMP_MESSAGE_ARG, false );            break;        }        // Update the head pointer after handling the message, so that        // the wait in cyg_hal_cpu_message() completes after the action        // requested.                m->head = (m->head + 1) & (SMP_MSGBUF_SIZE-1);    }    HAL_SPINLOCK_CLEAR( m->lock );        HAL_RESTORE_INTERRUPTS( istate );    return ret;}/*------------------------------------------------------------------------*/// CPU message DSR.// This is only executed if the message was// HAL_SMP_MESSAGE_RESCHEDULE. It calls up into the kernel to effect a// reschedule.__externC void cyg_scheduler_set_need_reschedule(void);__externC void cyg_scheduler_timeslice_cpu(void);#if SCREEN_DIAGNOSTICS__externC int cyg_scheduler_sched_lock;static int rescheds[2];static int timeslices[2];#endif__externC CYG_WORD32 cyg_hal_cpu_message_dsr( CYG_WORD32 vector, CYG_ADDRWORD data ){    HAL_SMP_CPU_TYPE me = HAL_SMP_CPU_THIS();    struct smp_msg_t *m = &smp_msg[me];    CYG_INTERRUPT_STATE istate;    CYG_WORD32 reschedule, timeslice;        HAL_DISABLE_INTERRUPTS( istate );    HAL_SPINLOCK_SPIN( m->lock );#if SCREEN_DIAGNOSTICS        dsrs[me]++;        PC_WRITE_SCREEN_16( PC_SCREEN_LINE(18+me)+10, dsrs[me]);    PC_WRITE_SCREEN_16( PC_SCREEN_LINE(18+me)+15, cyg_scheduler_sched_lock);  #endif        reschedule = m->reschedule;    timeslice = m->timeslice;    m->reschedule = m->timeslice = false;    HAL_SPINLOCK_CLEAR( m->lock );        HAL_RESTORE_INTERRUPTS( istate );            if( reschedule )    {#if SCREEN_DIAGNOSTICS                rescheds[me]++;        PC_WRITE_SCREEN_16( PC_SCREEN_LINE(18+me)+20, rescheds[me]);#endif                cyg_scheduler_set_need_reschedule();    }    if( timeslice )    {#if SCREEN_DIAGNOSTICS        timeslices[me]++;        PC_WRITE_SCREEN_16( PC_SCREEN_LINE(18+me)+25, timeslices[me]);#endif                cyg_scheduler_timeslice_cpu();    }    return 0;    }/*------------------------------------------------------------------------*/#if SCREEN_DIAGNOSTICSstatic int x = 0;#endif__externC void cyg_hal_smp_halt_other_cpus(void){    int i;    HAL_SMP_CPU_TYPE me = HAL_SMP_CPU_THIS();    //    PC_WRITE_SCREEN_8( PC_SCREEN_LINE(6+me), me );      for( i = 0 ; i < HAL_SMP_CPU_COUNT(); i++ )    {        if( i != me && cyg_hal_smp_cpu_running[i] )        {            CYG_WORD32 icrhi, icrlo;            CYG_WORD32 oldsync;            //            PC_WRITE_SCREEN_8( PC_SCREEN_LINE(6+me)+40, i );            oldsync = cyg_hal_smp_cpu_sync_flag[i];             cyg_hal_smp_cpu_sync[i] = 0;            icrhi = i<<24;            icrlo = CYGNUM_HAL_VECTOR_NMI;  // not really used            icrlo |= 0x00000400;    // Delivery = NMI            //icrlo |= 0x000C0000;    // Dest = all excluding self            // Write the ICR register. The interrupt will be raised when            // the low word is written.            HAL_APIC_WRITE( HAL_APIC_ICR_HI, icrhi );            HAL_APIC_WRITE( HAL_APIC_ICR_LO, icrlo );            // Wait for the ICR to become inactive            do {#if 0 //SCREEN_DIAGNOSTICS                static int n;                                PC_WRITE_SCREEN_8( PC_SCREEN_LINE(6+me)+45, n );                n++;#endif                                HAL_APIC_READ( HAL_APIC_ICR_LO, icrlo );            } while( (icrlo & 0x00001000) != 0 );            // Wait for CPU to halt            while( cyg_hal_smp_cpu_sync_flag[i] == oldsync )            {#if 0 //SCREEN_DIAGNOSTICS                                PC_WRITE_SCREEN_8( PC_SCREEN_LINE(6+me)+4, x ); x++;                PC_WRITE_SCREEN_8( PC_SCREEN_LINE(6+me)+10+(i*8), cyg_hal_smp_cpu_sync_flag[i] );                PC_WRITE_SCREEN_8( PC_SCREEN_LINE(6+me)+10+(i*8)+4, oldsync );#endif                           hal_delay_us( 100 );            }                    }    }    }__externC void cyg_hal_smp_release_other_cpus(void){    int i;    for( i = 0 ; i < HAL_SMP_CPU_COUNT(); i++ )    {        if( i != HAL_SMP_CPU_THIS() && cyg_hal_smp_cpu_running[i] )        {            CYG_WORD32 oldsync = cyg_hal_smp_cpu_sync_flag[i];                    cyg_hal_smp_cpu_sync[i] = 1;            while( cyg_hal_smp_cpu_sync_flag[i] == oldsync )                continue;            cyg_hal_smp_cpu_sync[i] = 0;        }    }}#endif // CYGPKG_HAL_SMP_SUPPORT/*------------------------------------------------------------------------*//* End of pcmb_smp.c                                                      */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -