Mercurial > ecos-v2_0-branch
changeset 62:7a6ac9edc838 ecos-sw-2000-01-24
Merge from eCos master repository on 2000-01-24-19:43:49-GMT
line wrap: on
line diff
--- a/packages/hal/arm/edb7xxx/current/ChangeLog +++ b/packages/hal/arm/edb7xxx/current/ChangeLog @@ -1,3 +1,13 @@ +2000-01-03 Gary Thomas <gthomas@cygnus.co.uk> + + * src/edb7xxx_misc.c: Need to re-enable FIQ during software "refresh", + no matter what method is being used [implicit or explicit]. + +1999-12-21 Gary Thomas <gthomas@cygnus.co.uk> + + * include/hal_platform_extras.h: Map in expansion segments (used + for ethernet and parallel port). + 1999-12-14 Jonathan Larmour <jlarmour@cygnus.co.uk> * support/Makefile: Update filenames from earlier source file change,
--- a/packages/hal/arm/edb7xxx/current/include/hal_platform_extras.h +++ b/packages/hal/arm/edb7xxx/current/include/hal_platform_extras.h @@ -135,8 +135,8 @@ FILL_16M_SEGMENT(MMU_L1_TYPE_Fault,0x00) FILL_16M_SEGMENT(MMU_L1_TYPE_Fault,0x00) FILL_256M_SEGMENT(MMU_L1_TYPE_Fault) - FILL_256M_SEGMENT(MMU_L1_TYPE_Fault) - FILL_256M_SEGMENT(MMU_L1_TYPE_Fault) + FILL_256M_SEGMENT(EXPANSION2_PA|MMU_L1_TYPE_Section|MMU_AP_Any) + FILL_256M_SEGMENT(EXPANSION3_PA|MMU_L1_TYPE_Section|MMU_AP_Any) FILL_256M_SEGMENT(MMU_L1_TYPE_Fault) FILL_256M_SEGMENT(MMU_L1_TYPE_Fault) FILL_256M_SEGMENT(SRAM_PA|MMU_L1_TYPE_Section|MMU_AP_Any)
--- a/packages/hal/arm/edb7xxx/current/misc/PKGconf.mak +++ b/packages/hal/arm/edb7xxx/current/misc/PKGconf.mak @@ -47,8 +47,3 @@ ifdef CYG_HAL_STARTUP_STUBS gdb_module.bin: gdb_module.stamp $(OBJCOPY) -O binary gdb_module$(EXEEXT) gdb_module.bin endif - - - - -
--- a/packages/hal/arm/edb7xxx/current/src/edb7xxx_misc.c +++ b/packages/hal/arm/edb7xxx/current/src/edb7xxx_misc.c @@ -91,12 +91,6 @@ void hal_clock_initialize(cyg_uint32 per // This routine is called during a clock interrupt. -#ifdef CYGHWR_HAL_ARM_EDB7XXX_SOFTWARE_DRAM_REFRESH -#define DRAM_START 0x00000000 -#define DRAM_END 0x01000000 -#define DRAM_ROW_SIZE 0x00000400 -#define DRAM_REFRESH (((DRAM_END-DRAM_START)/DRAM_ROW_SIZE)+99)/100 - static void __inline__ enable_FIQ(void) { @@ -105,13 +99,18 @@ enable_FIQ(void) "msr cpsr,r0"); } +#ifdef CYGHWR_HAL_ARM_EDB7XXX_SOFTWARE_DRAM_REFRESH +#define DRAM_START 0x00000000 +#define DRAM_END 0x01000000 +#define DRAM_ROW_SIZE 0x00000400 +#define DRAM_REFRESH (((DRAM_END-DRAM_START)/DRAM_ROW_SIZE)+99)/100 + static void do_DRAM_refresh(void) { static cyg_uint32 *row_ptr; volatile cyg_uint32 val; int i; - enable_FIQ(); // Should be safe here for (i = 0; i < DRAM_REFRESH; i++) { val = *row_ptr; row_ptr += DRAM_ROW_SIZE / sizeof(*row_ptr); @@ -127,6 +126,7 @@ void hal_clock_reset(cyg_uint32 vector, *tc2d = period; _period = period; } + enable_FIQ(); // Should be safe here #ifdef CYGHWR_HAL_ARM_EDB7XXX_SOFTWARE_DRAM_REFRESH do_DRAM_refresh(); #else
--- a/packages/hal/common/current/ChangeLog +++ b/packages/hal/common/current/ChangeLog @@ -1,3 +1,11 @@ +1999-12-21 Jonathan Larmour <jlarmour@cygnus.co.uk> + + * include/pkgconf/hal.h: Rename all CYG_HAL_USE_ROM_MONITOR_GDB_STUBS + -> CYGSEM_HAL_USE_ROM_MONITOR_GDB_stubs + Rename all CYG_HAL_USE_ROM_MONITOR_CYGMON -> + CYGSEM_HAL_USE_ROM_MONITOR_CygMon + Rename all CYG_HAL_USE_ROM_MONITOR -> CYGSEM_HAL_USE_ROM_MONITOR + 1999-11-20 Gary Thomas <gthomas@cygnus.co.uk> * include/pkgconf/hal.h (CYGSEM_HAL_INSTALL_MMU_TABLES):
--- a/packages/hal/common/current/include/pkgconf/hal.h +++ b/packages/hal/common/current/include/pkgconf/hal.h @@ -456,12 +456,12 @@ //#define CYG_HAL_USE_ROM_MONITOR #if defined(CYG_HAL_MIPS_TX39_JMR3904) && defined(CYG_HAL_STARTUP_RAM) -#define CYG_HAL_USE_ROM_MONITOR -#define CYG_HAL_USE_ROM_MONITOR_CYGMON +#define CYGSEM_HAL_USE_ROM_MONITOR +#define CYGSEM_HAL_USE_ROM_MONITOR_CygMon #endif #if defined(CYG_HAL_MN10300_AM31_STDEVAL1) && defined(CYG_HAL_STARTUP_RAM) -#define CYG_HAL_USE_ROM_MONITOR -#define CYG_HAL_USE_ROM_MONITOR_CYGMON +#define CYGSEM_HAL_USE_ROM_MONITOR +#define CYGSEM_HAL_USE_ROM_MONITOR_CygMon #endif #ifdef CYG_HAL_USE_ROM_MONITOR @@ -516,7 +516,6 @@ # define CYG_HAL_POWERPC_MPC603 #endif - #include CYGBLD_HAL_TARGET_H #include CYGBLD_HAL_PLATFORM_H
--- a/packages/hal/i386/arch/current/ChangeLog +++ b/packages/hal/i386/arch/current/ChangeLog @@ -1,3 +1,13 @@ +2000-01-21 Jesper Skov <jskov@cygnus.co.uk> + + * include/hal_intr.h (HAL_INTERRUPT_MASK, HAL_INTERRUPT_UNMASK): + Define. + + (HAL_INTERRUPT_ACKNOWLEDGE): + (HAL_CLOCK_RESET): + Let acknowledge clear pending flag, but leave unblocking to + clients of the interrupt (i.e., RTC). + 1999-10-25 Jonathan Larmour <jlarmour@cygnus.co.uk> * src/i386.ld: Add asterisks to input section names to make them more
--- a/packages/hal/i386/arch/current/include/hal_intr.h +++ b/packages/hal/i386/arch/current/include/hal_intr.h @@ -164,6 +164,9 @@ externC void cyg_hal_default_interrupt_v externC void cyg_hal_default_exception_vsr(int vector); externC int cyg_hal_sys_sigprocmask(int, const long*, long*); +// FIXME: These should use block/unblock of the signals instead of +// cyg_hal_interrupts_disabled. + #define HAL_ENABLE_INTERRUPTS() \ CYG_MACRO_START \ cyg_ucount8 _i_; \ @@ -205,15 +208,9 @@ externC int cyg_hal_sys_sigprocmask(int (_old_) = !cyg_hal_interrupts_disabled; \ CYG_MACRO_END -// FIXME: Must interract with the disable/enable macro. -// --proven 19981005 -#define LINUX_SIG_UNBLOCK 1 #define HAL_INTERRUPT_ACKNOWLEDGE( _vector_ ) \ CYG_MACRO_START \ - long _old_, _new_; \ - _new_ = 0xffffffff; \ cyg_hal_interrupts_unhandled[_vector_] = 0; \ - cyg_hal_sys_sigprocmask(LINUX_SIG_UNBLOCK, &_new_, &_old_); \ CYG_MACRO_END #endif // ifdef CYGPKG_HAL_I386_LINUX @@ -288,16 +285,20 @@ externC cyg_uint32 cyg_hal_default_isr(C #ifdef CYGPKG_HAL_I386_LINUX +#define LINUX_SIG_BLOCK 0 +#define LINUX_SIG_UNBLOCK 1 #define HAL_INTERRUPT_MASK( _vector_ ) \ CYG_MACRO_START \ - /* Use sigblock to mask a vector */ \ - CYG_EMPTY_STATEMENT; \ + long _old_, _new_; \ + _new_ = 1 << (_vector_); \ + cyg_hal_sys_sigprocmask(LINUX_SIG_BLOCK, &_new_, &_old_); \ CYG_MACRO_END #define HAL_INTERRUPT_UNMASK( _vector_ ) \ CYG_MACRO_START \ - /* Use sigunblock to mask a vector */ \ - CYG_EMPTY_STATEMENT; \ + long _old_, _new_; \ + _new_ = 1 << (_vector_); \ + cyg_hal_sys_sigprocmask(LINUX_SIG_UNBLOCK, &_new_, &_old_); \ CYG_MACRO_END // The native linux port doesn't have configurable interrupts. @@ -345,8 +346,9 @@ externC int cyg_hal_sys_getitimer(int, s cyg_hal_sys_setitimer(CYGNUM_HAL_TIMER_TYPE, &new_itimerval, &old); \ CYG_MACRO_END -// The clock reinitializes itself. -#define HAL_CLOCK_RESET( _vector_, _period_ ) +// The sigalarm runs in one-shot mode. We have to re-enable it +#define HAL_CLOCK_RESET( _vector_, _period_ ) \ + HAL_INTERRUPT_UNMASK( _vector_ ) // This timer counts down, so subtract from set value. #define HAL_CLOCK_READ( _pvalue_ ) \
--- a/packages/hal/i386/linux/current/ChangeLog +++ b/packages/hal/i386/linux/current/ChangeLog @@ -1,3 +1,11 @@ +2000-01-21 Jesper Skov <jskov@cygnus.co.uk> + CR 902062-CR + * src/hal_diag.c: + * src/syscall-i386-linux-1.0.S: + Sync after write. + + * src/hal_startup.c: Make signals NODEFER. + 1999-11-25 Gary Thomas <gthomas@cygnus.co.uk> * include/pkgconf/mlt_i386_linux_ram.h: New file(s).
--- a/packages/hal/i386/linux/current/src/hal_diag.c +++ b/packages/hal/i386/linux/current/src/hal_diag.c @@ -53,6 +53,7 @@ void hal_diag_init( void ) externC unsigned long cyg_hal_sys_write(int, const void*, long); externC unsigned long cyg_hal_sys_read(int, void*, long); +externC unsigned long cyg_hal_sys_fdatasync(int); // Write characters to a buffer which is flushed at newline/overflow to // improve performance. @@ -65,6 +66,7 @@ void hal_diag_write_char(char __c) if ('\n' == __c || 128 == __index) { cyg_hal_sys_write(1, &__buffer[0], __index); + cyg_hal_sys_fdatasync(1); __index = 0; } }
--- a/packages/hal/i386/linux/current/src/hal_startup.c +++ b/packages/hal/i386/linux/current/src/hal_startup.c @@ -135,6 +135,14 @@ cyg_hal_default_isr(CYG_ADDRWORD vector, //----------------------------------------------------------------------------- // Initialization on the VSRs. + +// Mark signals NODEFER (i.e., allow a signal to interrupt a running +// signal handler). This is necessary because we may switch to another +// thread in the signal handler and thus delay (indefinitely) the +// return of the "signal handler", postponing new signals during that +// time. +#define LINUX_SA_NODEFER 0x40000000 + struct hal_sigaction { void (*hal_handler)(int); long hal_mask; @@ -155,13 +163,13 @@ externC void cyg_hal_isr_init(void) // Interrupt VSR setup act.hal_handler = cyg_hal_default_interrupt_vsr; act.hal_mask = 0; - act.hal_flags = 0; + act.hal_flags = LINUX_SA_NODEFER; cyg_hal_sys_sigaction(CYGNUM_HAL_INTERRUPT_RTC, &act, &oact); // Exception VSR setup act.hal_handler = cyg_hal_default_exception_vsr; act.hal_mask = 0; - act.hal_flags = 0; + act.hal_flags = LINUX_SA_NODEFER; cyg_hal_sys_sigaction(CYGNUM_HAL_VECTOR_SIGSEGV, &act, &oact); cyg_hal_sys_sigaction(CYGNUM_HAL_VECTOR_SIGBUS, &act, &oact); cyg_hal_sys_sigaction(CYGNUM_HAL_VECTOR_SIGFPE, &act, &oact);
--- a/packages/hal/i386/linux/current/src/syscall-i386-linux-1.0.S +++ b/packages/hal/i386/linux/current/src/syscall-i386-linux-1.0.S @@ -347,7 +347,7 @@ NAME(x): // read 3 newselect 142 // write 4 readv 145 // open 5 writev 146 -// creat 8 +// creat 8 fdatasync 148 // link 9 // unlink 10 // execve 11 @@ -578,3 +578,7 @@ SYSCALL3(writev) //========================================================================== // machdep_sys_newselect() SYSCALL5(_newselect) + +//========================================================================== +// machdep_sys_fdatasync() +SYSCALL1(fdatasync)
--- a/packages/hal/mips/arch/current/ChangeLog +++ b/packages/hal/mips/arch/current/ChangeLog @@ -1,3 +1,44 @@ +2000-01-14 Nick Garnett <nickg@cygnus.co.uk> + + * include/hal_arch.h: + * include/arch.inc: + * src/vectors.S: + * src/context.S: + Several fixes to allow the GPRs to be saved + and restored as 64 bit values on some architectures. This is not + full 64 bit support since it only covers the GPRs, HI and LO, + there is more to be done in the CP0 registers (however it is a + start). + +1999-12-21 Jonathan Larmour <jlarmour@cygnus.co.uk> + + * src/vectors.S (__default_exception_vsr): Rename + CYG_HAL_USE_ROM_MONITOR_CYGMON -> CYGSEM_HAL_USE_ROM_MONITOR_CygMon + Rename CYG_HAL_ROM_MONITOR -> CYGSEM_HAL_ROM_MONITOR + + * src/hal_misc.c (hal_default_isr): Rename CYG_HAL_USE_ROM_MONITOR_CYGMON + -> CYGSEM_HAL_USE_ROM_MONITOR_CygMon + + * include/arch.inc: Rename CYG_HAL_USE_ROM_MONITOR -> + CYGSEM_HAL_USE_ROM_MONITOR + +1999-12-17 Jonathan Larmour <jlarmour@cygnus.co.uk> + + * src/mipsfp.c (flt2reg): New inline function to convert between + float union and register type + (reg2flt): Likewise in reverse + (cyg_hal_mips_process_fpe): Handle endianness correctly using the above + functions. Avoid possible aliasing problems with the compiler. Ensure + values are zeroed with the correct sign. Check for denormalized operands + for all remaining FPU opcodes. + + * src/hal_misc.c (cyg_hal_exception_handler): Allow handling of + unimplemented operation FPU exceptions to be configurable + * include/pkgconf/hal_mips.h: Provide + CYGSEM_HAL_MIPS_EMULATE_UNIMPLEMENTED_FPU_OPS to do this + + All the above required for cases 102817 and 102820 + 1999-12-15 Jonathan Larmour <jlarmour@cygnus.co.uk> * include/hal_intr.h (CYGNUM_HAL_EXCEPTION_COUNT): Ensure you can
--- a/packages/hal/mips/arch/current/include/arch.inc +++ b/packages/hal/mips/arch/current/include/arch.inc @@ -56,7 +56,7 @@ #ifndef INITIAL_SR #if defined(CYG_HAL_STARTUP_RAM) -# if defined(CYG_HAL_MIPS_SIM) || !defined(CYG_HAL_USE_ROM_MONITOR) +# if defined(CYG_HAL_MIPS_SIM) || !defined(CYGSEM_HAL_USE_ROM_MONITOR) # define INITIAL_SR 0x1000ff00 /* CP0 usable, Ints enabled */ # else # define INITIAL_SR 0x1040ff00 /* as above + ROM vectors used */ @@ -87,6 +87,8 @@ # define mips_regsize 4 #endif +# define mips_regsize32 4 + #if defined(CYGHWR_HAL_MIPS_FPU) # if defined(CYGHWR_HAL_MIPS_FPU_64BIT) # define mips_fpuregsize 8 @@ -104,19 +106,19 @@ #ifdef CYGHWR_HAL_MIPS_FPU # define mipsreg_fpureg (mipsreg_lo+mips_regsize) # define mipsreg_fcr31 (mipsreg_fpureg+(mips_fpuregsize*32)) -# define mipsreg_fppad (mipsreg_fcr31+mips_regsize) -# define mipsreg_vector (mipsreg_fppad+mips_regsize) +# define mipsreg_fppad (mipsreg_fcr31+mips_regsize32) +# define mipsreg_vector (mipsreg_fppad+mips_regsize32) #else -# define mipsreg_vector (mipsreg_lo+mips_regsize) +# define mipsreg_vector (mipsreg_lo+mips_regsize32) #endif -#define mipsreg_pc (mipsreg_vector+mips_regsize) -#define mipsreg_sr (mipsreg_pc+mips_regsize) -#define mipsreg_cachectrl (mipsreg_sr+mips_regsize) -#define mipsreg_cause (mipsreg_cachectrl+mips_regsize) -#define mipsreg_badvr (mipsreg_cause+mips_regsize) -#define mipsreg_prid (mipsreg_badvr+mips_regsize) -#define mipsreg_config (mipsreg_prid+mips_regsize) -#define mipsreg_size (mipsreg_config+mips_regsize) +#define mipsreg_pc (mipsreg_vector+mips_regsize32) +#define mipsreg_sr (mipsreg_pc+mips_regsize32) +#define mipsreg_cachectrl (mipsreg_sr+mips_regsize32) +#define mipsreg_cause (mipsreg_cachectrl+mips_regsize32) +#define mipsreg_badvr (mipsreg_cause+mips_regsize32) +#define mipsreg_prid (mipsreg_badvr+mips_regsize32) +#define mipsreg_config (mipsreg_prid+mips_regsize32) +#define mipsreg_size (mipsreg_config+mips_regsize32) #define mips_exception_decrement (mipsreg_size*2) @@ -329,6 +331,81 @@ hal_intc_translation_table: #endif #------------------------------------------------------------------------------ +# Register save and restore macros. These expect a pointer to a CPU save state +# area in the register \ptr. The GPR indicated by \reg will be saved into its +# slot in that structure. + +#ifdef CYGHWR_HAL_MIPS_64BIT + + .macro sgpr reg,ptr + sd $\reg,(mipsreg_regs+\reg*mips_regsize)(\ptr) + .endm + + .macro lgpr reg,ptr + ld $\reg,(mipsreg_regs+\reg*mips_regsize)(\ptr) + .endm + + .macro slo reg,ptr + sd \reg,(mipsreg_lo)(\ptr) + .endm + + .macro shi reg,ptr + sd \reg,(mipsreg_hi)(\ptr) + .endm + + .macro llo reg,ptr + ld \reg,(mipsreg_lo)(\ptr) + .endm + + .macro lhi reg,ptr + ld \reg,(mipsreg_hi)(\ptr) + .endm + + .macro ssp reg,ptr + sd \reg,(mipsreg_regs+29*mips_regsize)(\ptr) + .endm + + .macro lsp reg,ptr + ld \reg,(mipsreg_regs+29*mips_regsize)(\ptr) + .endm + +#else + + .macro sgpr reg,ptr + sw $\reg,(mipsreg_regs+\reg*mips_regsize)(\ptr) + .endm + + .macro lgpr reg,ptr + lw $\reg,(mipsreg_regs+\reg*mips_regsize)(\ptr) + .endm + + .macro slo reg,ptr + sw \reg,(mipsreg_lo)(\ptr) + .endm + + .macro shi reg,ptr + sw \reg,(mipsreg_hi)(\ptr) + .endm + + .macro llo reg,ptr + lw \reg,(mipsreg_lo)(\ptr) + .endm + + .macro lhi reg,ptr + lw \reg,(mipsreg_hi)(\ptr) + .endm + + .macro ssp reg,ptr + sw \reg,(mipsreg_regs+29*mips_regsize)(\ptr) + .endm + + .macro lsp reg,ptr + lw \reg,(mipsreg_regs+29*mips_regsize)(\ptr) + .endm + +#endif + +#------------------------------------------------------------------------------ # FPU macros. # The MIPS floating point unit essentially operates in two modes. In the first # it supplies 32 32bit FP registers that may be paired into 16 64 bit registers.
--- a/packages/hal/mips/arch/current/include/hal_arch.h +++ b/packages/hal/mips/arch/current/include/hal_arch.h @@ -49,9 +49,17 @@ //-------------------------------------------------------------------------- // Processor saved states: -// The layout of this structure is also defined in "mips.inc", for assembly +// The layout of this structure is also defined in "arch.inc", for assembly // code. Do not change this without changing that (or vice versa). +#ifdef CYGHWR_HAL_MIPS_64BIT +# define CYG_HAL_MIPS_REG CYG_WORD64 +# define CYG_HAL_MIPS_REG_SIZE 8 +#else +# define CYG_HAL_MIPS_REG CYG_WORD32 +# define CYG_HAL_MIPS_REG_SIZE 4 +#endif + #if defined(CYGHWR_HAL_MIPS_FPU) # if defined(CYGHWR_HAL_MIPS_FPU_64BIT) # define CYG_HAL_FPU_REG CYG_WORD64 @@ -65,9 +73,9 @@ typedef struct { // These are common to all saved states - CYG_ADDRWORD d[32]; /* Data regs */ - CYG_ADDRWORD hi; /* hi word of mpy/div reg */ - CYG_ADDRWORD lo; /* lo word of mpy/div reg */ + CYG_HAL_MIPS_REG d[32]; /* Data regs */ + CYG_HAL_MIPS_REG hi; /* hi word of mpy/div reg */ + CYG_HAL_MIPS_REG lo; /* lo word of mpy/div reg */ #ifdef CYGHWR_HAL_MIPS_FPU CYG_HAL_FPU_REG f[32]; /* FPU registers */ CYG_ADDRWORD fcr31; /* FPU control/status register */ @@ -132,24 +140,24 @@ externC cyg_uint32 hal_msbit_index(cyg_u // _thread_ thread object address, passed as argument to entry point // _entry_ entry point address. // _id_ bit pattern used in initializing registers, for debugging. -#define HAL_THREAD_INIT_CONTEXT( _sparg_, _thread_, _entry_, _id_ ) \ -{ \ - register CYG_WORD _sp_ = ((CYG_WORD)_sparg_)-56; \ - register HAL_SavedRegisters *_regs_; \ - int _i_; \ - _sp_ = _sp_ & 0xFFFFFFF0; \ +#define HAL_THREAD_INIT_CONTEXT( _sparg_, _thread_, _entry_, _id_ ) \ +{ \ + register CYG_WORD _sp_ = ((CYG_WORD)_sparg_)-56; \ + register HAL_SavedRegisters *_regs_; \ + int _i_; \ + _sp_ = _sp_ & 0xFFFFFFF0; \ _regs_ = (HAL_SavedRegisters *)(((_sp_) - sizeof(HAL_SavedRegisters))&0xFFFFFFF0); \ - for( _i_ = 0; _i_ < 32; _i_++ ) (_regs_)->d[_i_] = (_id_)|_i_; \ - HAL_THREAD_INIT_FPU_CONTEXT( _regs_, _id_ ); \ - (_regs_)->d[29] = (CYG_WORD)(_sp_); /* SP = top of stack */ \ - (_regs_)->d[04] = (CYG_WORD)(_thread_); /* R4 = arg1 = thread ptr */ \ - (_regs_)->lo = 0; /* LO = 0 */ \ - (_regs_)->hi = 0; /* HI = 0 */ \ - (_regs_)->d[30] = (CYG_WORD)(_sp_); /* FP = top of stack */ \ - (_regs_)->d[31] = (CYG_WORD)(_entry_); /* LR(d[31]) = entry point*/ \ - (_regs_)->pc = (CYG_WORD)(_entry_); /* PC = entry point */ \ - (_regs_)->sr = 0x00000001; /* SR = ls 3 bits only */ \ - _sparg_ = (CYG_ADDRESS)_regs_; \ + for( _i_ = 0; _i_ < 32; _i_++ ) (_regs_)->d[_i_] = (_id_)|_i_; \ + HAL_THREAD_INIT_FPU_CONTEXT( _regs_, _id_ ); \ + (_regs_)->d[29] = (CYG_HAL_MIPS_REG)(_sp_); /* SP = top of stack */ \ + (_regs_)->d[04] = (CYG_HAL_MIPS_REG)(_thread_); /* R4 = arg1 = thread ptr */ \ + (_regs_)->lo = 0; /* LO = 0 */ \ + (_regs_)->hi = 0; /* HI = 0 */ \ + (_regs_)->d[30] = (CYG_HAL_MIPS_REG)(_sp_); /* FP = top of stack */ \ + (_regs_)->d[31] = (CYG_HAL_MIPS_REG)(_entry_); /* RA(d[31]) = entry point*/ \ + (_regs_)->pc = (CYG_WORD)(_entry_); /* PC = entry point */ \ + (_regs_)->sr = 0x00000001; /* SR = ls 3 bits only */ \ + _sparg_ = (CYG_ADDRESS)_regs_; \ } //-------------------------------------------------------------------------- @@ -313,11 +321,6 @@ externC void hal_idle_thread_action(cyg_ // THEY ARE HOWEVER ENOUGH TO START PROGRAMMING. // YOU MUST MAKE YOUR STACKS LARGER IF YOU HAVE LARGE "AUTO" VARIABLES! -// We define quite large stack needs for SPARClite, for it requires 576 -// bytes (144 words) to process an interrupt and thread-switch, and -// momentarily, but needed in case of recursive interrupts, it needs 208 -// words - if a sequence of saves to push out other regsets is interrupted. - // This is not a config option because it should not be adjusted except // under "enough rope" sort of disclaimers. @@ -327,14 +330,14 @@ externC void hal_idle_thread_action(cyg_ // Stack needed for a context switch: #if defined(CYGHWR_HAL_MIPS_FPU) # if defined(CYGHWR_HAL_MIPS_FPU_64BIT) -#define CYGNUM_HAL_STACK_CONTEXT_SIZE (((32+12)*4)+(32*8)) +#define CYGNUM_HAL_STACK_CONTEXT_SIZE (((32+12)*CYG_HAL_MIPS_REG_SIZE)+(32*8)) # elif defined(CYGHWR_HAL_MIPS_FPU_32BIT) -#define CYGNUM_HAL_STACK_CONTEXT_SIZE (((32+12)*4)+(32*4)) +#define CYGNUM_HAL_STACK_CONTEXT_SIZE (((32+12)*CYG_HAL_MIPS_REG_SIZE)+(32*4)) # else # error MIPS FPU register size not defined # endif #else -#define CYGNUM_HAL_STACK_CONTEXT_SIZE ((32+10)*4) +#define CYGNUM_HAL_STACK_CONTEXT_SIZE ((32+10)*CYG_HAL_MIPS_REG_SIZE) #endif
--- a/packages/hal/mips/arch/current/include/pkgconf/hal_mips.h +++ b/packages/hal/mips/arch/current/include/pkgconf/hal_mips.h @@ -76,9 +76,24 @@ memory access speed settings." } + cdl_option CYGSEM_HAL_MIPS_EMULATE_UNIMPLEMENTED_FPU_OPS { + display "Emulate unimplemented FPU opcodes" + type boolean + parent CYGPKG_HAL_MIPS + description " + Enabling this option will include a hook in the exception + processing so that Unimplemented Operation FPU exceptions + may be handled. This option has no effect if there is no + hardware floating-point unit. Note that not all situations + in which an exception is raised may be handled. If not, the + exception will be passed on as normal through the standard + exception delivery mechanism." + } + }}CFG_DATA */ #define CYGHWR_HAL_MIPS_CPU_FREQ 50 +#define CYGSEM_HAL_MIPS_EMULATE_UNIMPLEMENTED_FPU_OPS /* -------------------------------------------------------------------*/ /* If either the CTRLC or BREAK support options in hal.h are set */
--- a/packages/hal/mips/arch/current/src/context.S +++ b/packages/hal/mips/arch/current/src/context.S @@ -58,48 +58,48 @@ hal_thread_switch_context: # store GPRs .set noat #ifndef CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM - sw $0,(mipsreg_regs+0*mips_regsize)(sp) - sw $1,(mipsreg_regs+1*mips_regsize)(sp) - sw $2,(mipsreg_regs+2*mips_regsize)(sp) - sw $3,(mipsreg_regs+3*mips_regsize)(sp) - sw $4,(mipsreg_regs+4*mips_regsize)(sp) - sw $5,(mipsreg_regs+5*mips_regsize)(sp) - sw $6,(mipsreg_regs+6*mips_regsize)(sp) - sw $7,(mipsreg_regs+7*mips_regsize)(sp) - sw $8,(mipsreg_regs+8*mips_regsize)(sp) - sw $9,(mipsreg_regs+9*mips_regsize)(sp) - sw $10,(mipsreg_regs+10*mips_regsize)(sp) - sw $11,(mipsreg_regs+11*mips_regsize)(sp) - sw $12,(mipsreg_regs+12*mips_regsize)(sp) - sw $13,(mipsreg_regs+13*mips_regsize)(sp) - sw $14,(mipsreg_regs+14*mips_regsize)(sp) - sw $15,(mipsreg_regs+15*mips_regsize)(sp) - sw $24,(mipsreg_regs+24*mips_regsize)(sp) - sw $25,(mipsreg_regs+25*mips_regsize)(sp) - sw $28,(mipsreg_regs+28*mips_regsize)(sp) # == GP + sgpr 0,sp + sgpr 1,sp + sgpr 2,sp + sgpr 3,sp + sgpr 4,sp + sgpr 5,sp + sgpr 6,sp + sgpr 7,sp + sgpr 8,sp + sgpr 9,sp + sgpr 10,sp + sgpr 11,sp + sgpr 12,sp + sgpr 13,sp + sgpr 14,sp + sgpr 15,sp + sgpr 24,sp + sgpr 25,sp + sgpr 28,sp # == GP #endif - sw $16,(mipsreg_regs+16*mips_regsize)(sp) - sw $17,(mipsreg_regs+17*mips_regsize)(sp) - sw $18,(mipsreg_regs+18*mips_regsize)(sp) - sw $19,(mipsreg_regs+19*mips_regsize)(sp) - sw $20,(mipsreg_regs+20*mips_regsize)(sp) - sw $21,(mipsreg_regs+21*mips_regsize)(sp) - sw $22,(mipsreg_regs+22*mips_regsize)(sp) - sw $23,(mipsreg_regs+23*mips_regsize)(sp) -# sw $26,(mipsreg_regs+26*mips_regsize)(sp) # == K0 -# sw $27,(mipsreg_regs+27*mips_regsize)(sp) # == K1 -# sw $29,(mipsreg_regs+29*mips_regsize)(sp) # == SP - sw $30,(mipsreg_regs+30*mips_regsize)(sp) # == FP - sw $31,(mipsreg_regs+31*mips_regsize)(sp) # == RA - sw $31,(mipsreg_pc)(sp) # == PC (to help with debugging) + sgpr 16,sp + sgpr 17,sp + sgpr 18,sp + sgpr 19,sp + sgpr 20,sp + sgpr 21,sp + sgpr 22,sp + sgpr 23,sp +# sgpr 26,sp # == K0 +# sgpr 27,sp # == K1 +# sgpr 29,sp # == SP + sgpr 30,sp # == FP + sgpr 31,sp # == RA + sgpr 31,sp # == PC (to help with debugging) .set at #ifndef CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM mflo t0 # save LO and HI regs mfhi t1 - sw t0,mipsreg_lo(sp) - sw t1,mipsreg_hi(sp) + slo t0,sp + shi t1,sp #endif @@ -112,7 +112,7 @@ hal_thread_switch_context: #endif addi t0,sp,mipsreg_size # save SP in reg dump - sw t0,(mipsreg_regs+29*mips_regsize)(sp) + ssp t0,sp mfc0 t1,status # Save status register sw t1,mipsreg_sr(sp) @@ -153,44 +153,44 @@ hal_thread_load_context: # load GPRs .set noat -# lw $0,(mipsreg_regs+0*mips_regsize)(sp) - lw $4,(mipsreg_regs+4*mips_regsize)(sp) # A0, must load for thread startup +# lgpr 0,sp + lgpr 4,sp # A0, must load for thread startup #ifndef CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM - lw $1,(mipsreg_regs+1*mips_regsize)(sp) - lw $2,(mipsreg_regs+2*mips_regsize)(sp) - lw $3,(mipsreg_regs+3*mips_regsize)(sp) - lw $5,(mipsreg_regs+5*mips_regsize)(sp) - lw $6,(mipsreg_regs+6*mips_regsize)(sp) - lw $7,(mipsreg_regs+7*mips_regsize)(sp) - lw $8,(mipsreg_regs+8*mips_regsize)(sp) - lw $9,(mipsreg_regs+9*mips_regsize)(sp) - lw $10,(mipsreg_regs+10*mips_regsize)(sp) - lw $11,(mipsreg_regs+11*mips_regsize)(sp) - lw $12,(mipsreg_regs+12*mips_regsize)(sp) - lw $13,(mipsreg_regs+13*mips_regsize)(sp) - lw $14,(mipsreg_regs+14*mips_regsize)(sp) - lw $15,(mipsreg_regs+15*mips_regsize)(sp) - lw $24,(mipsreg_regs+24*mips_regsize)(sp) - lw $25,(mipsreg_regs+25*mips_regsize)(sp) + lgpr 1,sp + lgpr 2,sp + lgpr 3,sp + lgpr 5,sp + lgpr 6,sp + lgpr 7,sp + lgpr 8,sp + lgpr 9,sp + lgpr 10,sp + lgpr 11,sp + lgpr 12,sp + lgpr 13,sp + lgpr 14,sp + lgpr 15,sp + lgpr 24,sp + lgpr 25,sp #endif - lw $16,(mipsreg_regs+16*mips_regsize)(sp) - lw $17,(mipsreg_regs+17*mips_regsize)(sp) - lw $18,(mipsreg_regs+18*mips_regsize)(sp) - lw $19,(mipsreg_regs+19*mips_regsize)(sp) - lw $20,(mipsreg_regs+20*mips_regsize)(sp) - lw $21,(mipsreg_regs+21*mips_regsize)(sp) - lw $22,(mipsreg_regs+22*mips_regsize)(sp) - lw $23,(mipsreg_regs+23*mips_regsize)(sp) -# lw $26,(mipsreg_regs+26*mips_regsize)(sp) # == K0 -# lw $27,(mipsreg_regs+27*mips_regsize)(sp) # == K1 -# lw $28,(mipsreg_regs+28*mips_regsize)(sp) # == GP -# lw $29,(mipsreg_regs+29*mips_regsize)(sp) # == SP - lw $30,(mipsreg_regs+30*mips_regsize)(sp) # == FP - lw $31,(mipsreg_regs+31*mips_regsize)(sp) # == RA + lgpr 16,sp + lgpr 17,sp + lgpr 18,sp + lgpr 19,sp + lgpr 20,sp + lgpr 21,sp + lgpr 22,sp + lgpr 23,sp +# lgpr 26,sp # == K0 +# lgpr 27,sp # == K1 +# lgpr 28,sp # == GP +# lgpr 29,sp # == SP + lgpr 30,sp # == FP + lgpr 31,sp # == RA .set at lw a2,mipsreg_sr(sp) # A2 = saved SR - lw sp,(mipsreg_regs+29*mips_regsize)(sp) # SP = saved SP + lsp sp,sp # SP = saved SP hal_cpu_int_merge a2 # Merge with current SR
--- a/packages/hal/mips/arch/current/src/hal_misc.c +++ b/packages/hal/mips/arch/current/src/hal_misc.c @@ -74,7 +74,8 @@ externC cyg_uint8 cyg_hal_mips_process_f externC cyg_uint32 cyg_hal_exception_handler(HAL_SavedRegisters *regs) { -#ifdef CYGHWR_HAL_MIPS_FPU +#if defined(CYGHWR_HAL_MIPS_FPU) && \ + defined(CYGSEM_HAL_MIPS_EMULATE_UNIMPLEMENTED_FPU_OPS) // We may be required to emulate certain unimplemented Floating Point // operations @@ -137,7 +138,7 @@ externC cyg_uint32 hal_default_isr(CYG_A if( result != 0 ) return result; } -#if defined(CYG_HAL_USE_ROM_MONITOR_CYGMON) +#if defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon) #if defined(HAL_DIAG_IRQ_CHECK) { cyg_uint32 ret; @@ -147,7 +148,7 @@ externC cyg_uint32 hal_default_isr(CYG_A return ret; } #endif // def HAL_DIAG_IRQ_CHECK -#endif // def CYG_HAL_USE_ROM_MONITOR +#endif // def CYGSEM_HAL_USE_ROM_MONITOR_CygMon #endif CYG_TRACE1(true, "Interrupt: %d", vector);
--- a/packages/hal/mips/arch/current/src/mipsfp.c +++ b/packages/hal/mips/arch/current/src/mipsfp.c @@ -263,7 +263,27 @@ typedef enum { // FUNCTIONS -#define issubnormal(_x_) ((_x_)->number.exponent == 0) +#define issubnormal(_x_) ((_x_).number.exponent == 0) + +// These functions convert between single precision floating point numbers +// represented in register or union form. This is required because endian-ness +// matters when a 32-bit float is in a 64-bit register. + +static __inline__ void +reg2flt( CYG_HAL_FPU_REG *fpu_reg_p, Cyg_libm_ieee_float_shape_type *flt) +{ +#if defined(CYGHWR_HAL_MIPS_FPU_32BIT) || (CYG_BYTEORDER == CYG_LSBFIRST) + flt->asi32 = *(cyg_int32 *)fpu_reg_p; +#else + flt->asi32 = *((cyg_int32 *)fpu_reg_p + 1); +# endif +} // reg2flt() + +static __inline__ void +flt2reg( Cyg_libm_ieee_float_shape_type *flt, CYG_HAL_FPU_REG *fpu_reg_p ) +{ + *fpu_reg_p = flt->asi32; +} // flt2reg() // This function returns non-zero if the exception has been handled // successfully. @@ -355,13 +375,18 @@ cyg_hal_mips_process_fpe( HAL_SavedRegis case DIV_INSN: if (fp64bit) { - Cyg_libm_ieee_double_shape_type *s1, *s2; + Cyg_libm_ieee_double_shape_type s1, s2; + + s1.asi64 = *srcreg1; + s2.asi64 = *srcreg2; - s1 = (Cyg_libm_ieee_double_shape_type *)srcreg1; - s2 = (Cyg_libm_ieee_double_shape_type *)srcreg2; - - if (issubnormal(s1)) { // flush to 0 and restart - s1->value=0.0; + if ( issubnormal( s1 ) ) { // flush to 0 and restart + // but preserve sign + if (s1.number.sign) + s1.value = -0.0; + else + s1.value = 0.0; + *srcreg1 = s1.asi64; handled++; } @@ -371,59 +396,95 @@ cyg_hal_mips_process_fpe( HAL_SavedRegis // get 0/0 even when the program explicitly checked for // denominator != 0. That's also why we check s1 first. - else if (issubnormal(s2)) { // flush to 0 and restart - s2->value=0.0; + else if ( issubnormal( s2 ) ) { // flush to 0 and restart + // but preserve sign + if (s2.number.sign) + s2.value = -0.0; + else + s2.value = 0.0; + *srcreg2 = s2.asi64; handled++; } + } else { // 32-bit - Cyg_libm_ieee_float_shape_type *s1, *s2; + Cyg_libm_ieee_float_shape_type s1, s2; + + reg2flt( srcreg1, &s1 ); + reg2flt( srcreg2, &s2 ); - s1 = (Cyg_libm_ieee_float_shape_type *)srcreg1; - s2 = (Cyg_libm_ieee_float_shape_type *)srcreg2; - - if (issubnormal(s1)) { // flush to 0 and restart - s1->value=0.0; + if ( issubnormal( s1 )) { // flush to 0 and restart + // but preserve sign + if (s1.number.sign) + s1.value = -0.0; + else + s1.value = 0.0; + flt2reg( &s1, srcreg1 ); handled++; } - else if (issubnormal(s2)) { // flush to 0 and restart - s2->value=0.0; + else if ( issubnormal( s2 ) ) { // flush to 0 and restart + // but preserve sign + if (s2.number.sign) + s2.value = -0.0; + else + s2.value = 0.0; + flt2reg( &s2, srcreg2 ); handled++; } } break; case SQRT_INSN: - if (fp64bit) { - Cyg_libm_ieee_double_shape_type *d, *s; + if ( fp64bit ) { + Cyg_libm_ieee_double_shape_type d, s; - d = (Cyg_libm_ieee_double_shape_type *)dstreg; - s = (Cyg_libm_ieee_double_shape_type *)srcreg1; + d.asi64 = *dstreg; + s.asi64 = *srcreg1; - if (issubnormal(s)) { // Sqrt of something tiny is 0 + if ( issubnormal( s ) ) { // Sqrt of something tiny is 0 // if this is a delay slot, we can't restart properly - // so clear the source register instead - if (delay_slot) - s->value=0.0; - else { - d->value=0.0; + // so if it is subnormal, clear the source register instead + if ( delay_slot ) { + // but preserve sign + if (s.number.sign) + s.value = -0.0; + else + s.value = 0.0; + *srcreg1 = s.asi64; + } else { + // but preserve sign + if (s.number.sign) + d.value = -0.0; + else + d.value = 0.0; + *dstreg = d.asi64; regs->pc += 4; // We've dealt with this so move on } handled++; } } else { // 32-bit - Cyg_libm_ieee_float_shape_type *d, *s; + Cyg_libm_ieee_float_shape_type d, s; - d = (Cyg_libm_ieee_float_shape_type *)dstreg; - s = (Cyg_libm_ieee_float_shape_type *)srcreg1; + reg2flt( dstreg, &d ); + reg2flt( srcreg1, &s ); - if (issubnormal(s)) { // Sqrt of something tiny is 0 + if ( issubnormal( s ) ) { // Sqrt of something tiny is 0 // if this is a delay slot, we can't restart properly - // so clear the source register instead - if (delay_slot) - s->value=0.0; - else { - d->value=0.0; + // so if it is subnormal, clear the source register instead + if ( delay_slot ) { + // but preserve sign + if (s.number.sign) + s.value = -0.0; + else + s.value = 0.0; + flt2reg( &s, srcreg1 ); + } else { + // but preserve sign + if (s.number.sign) + d.value = -0.0; + else + d.value = 0.0; + flt2reg( &d, dstreg ); regs->pc += 4; // We've dealt with this so move on } handled++; @@ -433,85 +494,282 @@ cyg_hal_mips_process_fpe( HAL_SavedRegis case ABS_INSN: // We may as well do this right if we can - if (fp64bit) { - Cyg_libm_ieee_double_shape_type *d, *s; + if ( fp64bit ) { + Cyg_libm_ieee_double_shape_type d, s; - d = (Cyg_libm_ieee_double_shape_type *)dstreg; - s = (Cyg_libm_ieee_double_shape_type *)srcreg1; + d.asi64 = *dstreg; + s.asi64 = *srcreg1; // if this is a delay slot, we can't restart properly - // so clear the source register instead - if (delay_slot) { - s->value=0.0; + // so if it is subnormal, clear the source register instead + if ( delay_slot ) { + if ( issubnormal( s ) ) { + // The sign is still important for abs in case + // there are any further operations on the same + // register + if (s.number.sign) + s.value = -0.0; + else + s.value = 0.0; + *srcreg1 = s.asi64; + handled++; + } } else { - d->asi64 = s->asi64; - d->number.sign = 0; + d.asi64 = s.asi64; + d.number.sign = 0; + *dstreg = d.asi64; regs->pc += 4; + handled++; } } else { // 32-bit - Cyg_libm_ieee_float_shape_type *d, *s; + Cyg_libm_ieee_float_shape_type d, s; + + reg2flt( dstreg, &d ); + reg2flt( srcreg1, &s ); - d = (Cyg_libm_ieee_float_shape_type *)dstreg; - s = (Cyg_libm_ieee_float_shape_type *)srcreg1; + // if this is a delay slot, we can't restart properly + // so if it is subnormal, clear the source register instead + if ( delay_slot ) { + if ( issubnormal( s ) ) { + // The sign is still important for abs in case + // there are any further operations on the same + // register + if (s.number.sign) + s.value = -0.0; + else + s.value = 0.0; + flt2reg( &s, srcreg1 ); + handled++; + } + } else { + d.asi32 = s.asi32; + d.number.sign = 0; + flt2reg( &d, dstreg ); + regs->pc += 4; + handled++; + } + } + break; + + case MOV_INSN: + // We may as well do this right if we can + if ( fp64bit ) { + Cyg_libm_ieee_double_shape_type d, s; + + d.asi64 = *dstreg; + s.asi64 = *srcreg1; // if this is a delay slot, we can't restart properly - // so clear the source register instead - if (delay_slot) { - s->value=0.0; + // so if it is subnormal, clear the source register instead + if ( delay_slot ) { + if ( issubnormal( s ) ) { + // but preserve sign + if (s.number.sign) + s.value = -0.0; + else + s.value = 0.0; + *srcreg1 = s.asi64; + handled++; + } } else { - d->asi32 = s->asi32; - d->number.sign = 0; + d.asi64 = s.asi64; + *dstreg = d.asi64; regs->pc += 4; + handled++; + } + } else { // 32-bit + Cyg_libm_ieee_float_shape_type d, s; + + reg2flt( dstreg, &d ); + reg2flt( srcreg1, &s ); + + // if this is a delay slot, we can't restart properly + // so if it is subnormal, clear the source register instead + if ( delay_slot ) { + if ( issubnormal( s ) ) { + // The sign is still important for abs in case + // there are any further operations on the same + // register + if (s.number.sign) + s.value = -0.0; + else + s.value = 0.0; + flt2reg( &s, srcreg1 ); + handled++; + } + } else { + d.asi32 = s.asi32; + flt2reg( &d, dstreg ); + regs->pc += 4; + handled++; } } - handled++; break; case NEG_INSN: // We may as well do this right if we can - if (fp64bit) { - Cyg_libm_ieee_double_shape_type *d, *s; + if ( fp64bit ) { + Cyg_libm_ieee_double_shape_type d, s; - d = (Cyg_libm_ieee_double_shape_type *)dstreg; - s = (Cyg_libm_ieee_double_shape_type *)srcreg1; + d.asi64 = *dstreg; + s.asi64 = *srcreg1; // if this is a delay slot, we can't restart properly - // so clear the source register instead - if (delay_slot) { - s->value=0.0; + // so if it is subnormal, clear the source register instead + if ( delay_slot ) { + if ( issubnormal( s ) ) { + // but preserve sign + if (s.number.sign) + s.value = -0.0; + else + s.value = 0.0; + *srcreg1 = s.asi64; + handled++; + } } else { - d->asi64 = s->asi64; - d->number.sign = s->number.sign ? 0 : 1; + d.asi64 = s.asi64; + d.number.sign = s.number.sign ? 0 : 1; + *dstreg = d.asi64; regs->pc += 4; + handled++; } } else { // 32-bit - Cyg_libm_ieee_float_shape_type *d, *s; + Cyg_libm_ieee_float_shape_type d, s; - d = (Cyg_libm_ieee_float_shape_type *)dstreg; - s = (Cyg_libm_ieee_float_shape_type *)srcreg1; + reg2flt( dstreg, &d ); + reg2flt( srcreg1, &s ); // if this is a delay slot, we can't restart properly - // so clear the source register instead - if (delay_slot) { - s->value=0.0; + // so if it is subnormal, clear the source register instead + if ( delay_slot ) { + if ( issubnormal( s ) ) { + // but preserve sign + if (s.number.sign) + s.value = -0.0; + else + s.value = 0.0; + flt2reg( &s, srcreg1 ); + handled++; + } } else { - d->asi32 = s->asi32; - d->number.sign = s->number.sign ? 0 : 1; + d.asi32 = s.asi32; + d.number.sign = s.number.sign ? 0 : 1; + flt2reg( &d, dstreg ); regs->pc += 4; + handled++; } } - handled++; + break; + + // We can't do much about floating-point to fixed-point arithmetic + // without emulating the FPU here ourselves! + // So simply zero denormalized numbers + case ROUNDL_INSN: + case TRUNCL_INSN: + case CEILL_INSN: + case FLOORL_INSN: + case ROUNDW_INSN: + case TRUNCW_INSN: + case CEILW_INSN: + case FLOORW_INSN: + case CVTS_INSN: + case CVTD_INSN: + case CVTW_INSN: + case CVTL_INSN: + + if ( fp64bit ) { + Cyg_libm_ieee_double_shape_type s; + + s.asi64 = *srcreg1; + + // just try and 0 the source register if it is subnormal + if ( issubnormal( s ) ) { + // but preserve sign + if (s.number.sign) + s.value = -0.0; + else + s.value = 0.0; + *srcreg1 = s.asi64; + handled++; + } + } else { // 32-bit + Cyg_libm_ieee_float_shape_type s; + + reg2flt( srcreg1, &s ); + + // just try and 0 the source register if it is subnormal + if ( issubnormal( s ) ) { + // but preserve sign + if (s.number.sign) + s.value = -0.0; + else + s.value = 0.0; + flt2reg( &s, srcreg1 ); + handled++; + } + } break; default: + // check for floating-point compare (C.cond.fmt) + if ( (insn & 0x30) == 0x30 ) { + if (fp64bit) { + Cyg_libm_ieee_double_shape_type s1, s2; + + s1.asi64 = *srcreg1; + s2.asi64 = *srcreg2; + + if ( issubnormal( s1 ) ) { // flush to 0 and restart + // but preserve sign + if (s1.number.sign) + s1.value = -0.0; + else + s1.value = 0.0; + *srcreg1 = s1.asi64; + handled++; + } + + if ( issubnormal( s2 ) ) { // flush to 0 and restart + // but preserve sign + if (s2.number.sign) + s2.value = -0.0; + else + s2.value = 0.0; + *srcreg2 = s2.asi64; + handled++; + } + + } else { // 32-bit + Cyg_libm_ieee_float_shape_type s1, s2; + + reg2flt( srcreg1, &s1 ); + reg2flt( srcreg2, &s2 ); + + if ( issubnormal( s1 )) { // flush to 0 and restart + // but preserve sign + if (s1.number.sign) + s1.value = -0.0; + else + s1.value = 0.0; + flt2reg( &s1, srcreg1 ); + handled++; + } + if ( issubnormal( s2 ) ) { // flush to 0 and restart + // but preserve sign + if (s2.number.sign) + s2.value = -0.0; + else + s2.value = 0.0; + flt2reg( &s2, srcreg2 ); + handled++; + } + } // else + } // if break; } // switch - - // As well as all the other opcodes in the enum, there are also all - // the floating point compare operations between 48 and 63 - } + } // if (computational_insn && !fixedpoint) - if (handled) { + if ( handled != 0) { // We must clear the cause and flag bits before restoring FPCR31 regs->fcr31 &= ~(FCR31_CAUSE_E | FCR31_CAUSE_V | FCR31_CAUSE_Z | FCR31_CAUSE_O | FCR31_CAUSE_U | FCR31_CAUSE_I | @@ -520,7 +778,7 @@ cyg_hal_mips_process_fpe( HAL_SavedRegis } - CYG_REPORT_RETVAL(handled); + CYG_REPORT_RETVAL( handled ); return handled; } // cyg_hal_mips_process_fpe()
--- a/packages/hal/mips/arch/current/src/vectors.S +++ b/packages/hal/mips/arch/current/src/vectors.S @@ -289,11 +289,11 @@ FUNC_START(__default_exception_vsr) move k1,sp # K1 = original SP -#ifdef CYG_HAL_ROM_MONITOR +#ifdef CYGSEM_HAL_ROM_MONITOR # Switch to interrupt stack to handle exception la sp,__interrupt_stack #endif - + addi sp,sp,-mips_exception_decrement # space for registers + safety margin @@ -301,47 +301,47 @@ FUNC_START(__default_exception_vsr) # store GPRs .set noat - sw $0,(mipsreg_regs+0*4)(sp) - sw $1,(mipsreg_regs+1*4)(sp) - sw $2,(mipsreg_regs+2*4)(sp) - sw $3,(mipsreg_regs+3*4)(sp) - sw $4,(mipsreg_regs+4*4)(sp) - sw $5,(mipsreg_regs+5*4)(sp) - sw $6,(mipsreg_regs+6*4)(sp) - sw $7,(mipsreg_regs+7*4)(sp) - sw $8,(mipsreg_regs+8*4)(sp) - sw $9,(mipsreg_regs+9*4)(sp) - sw $10,(mipsreg_regs+10*4)(sp) - sw $11,(mipsreg_regs+11*4)(sp) - sw $12,(mipsreg_regs+12*4)(sp) - sw $13,(mipsreg_regs+13*4)(sp) - sw $14,(mipsreg_regs+14*4)(sp) - sw $15,(mipsreg_regs+15*4)(sp) - sw $16,(mipsreg_regs+16*4)(sp) - sw $17,(mipsreg_regs+17*4)(sp) - sw $18,(mipsreg_regs+18*4)(sp) - sw $19,(mipsreg_regs+19*4)(sp) - sw $20,(mipsreg_regs+20*4)(sp) - sw $21,(mipsreg_regs+21*4)(sp) - sw $22,(mipsreg_regs+22*4)(sp) - sw $23,(mipsreg_regs+23*4)(sp) - sw $24,(mipsreg_regs+24*4)(sp) - sw $25,(mipsreg_regs+25*4)(sp) -# sw $26,(mipsreg_regs+26*4)(sp) # == K0 -# sw $27,(mipsreg_regs+27*4)(sp) # == K1 - sw $28,(mipsreg_regs+28*4)(sp) # == GP -# sw $29,(mipsreg_regs+29*4)(sp) # == SP - sw $30,(mipsreg_regs+30*4)(sp) # == FP - sw $31,(mipsreg_regs+31*4)(sp) # == RA + sgpr 0,sp + sgpr 1,sp + sgpr 2,sp + sgpr 3,sp + sgpr 4,sp + sgpr 5,sp + sgpr 6,sp + sgpr 7,sp + sgpr 8,sp + sgpr 9,sp + sgpr 10,sp + sgpr 11,sp + sgpr 12,sp + sgpr 13,sp + sgpr 14,sp + sgpr 15,sp + sgpr 16,sp + sgpr 17,sp + sgpr 18,sp + sgpr 19,sp + sgpr 20,sp + sgpr 21,sp + sgpr 22,sp + sgpr 23,sp + sgpr 24,sp + sgpr 25,sp +# sgpr 26,sp # == K0 +# sgpr 27,sp # == K1 + sgpr 28,sp # == GP +# sgpr 29,sp # == SP + sgpr 30,sp # == FP + sgpr 31,sp # == RA .set at mfhi a0 mflo a1 - sw a0,mipsreg_hi(sp) - sw a1,mipsreg_lo(sp) + shi a0,sp + slo a1,sp # K1 contains original SP - sw k1,(mipsreg_regs+29*4)(sp) # store in reg dump + ssp k1,sp # store in reg dump # save remaining machine state registers mfc0 t0,cause @@ -410,47 +410,47 @@ FUNC_START(__default_interrupt_vsr) # store GPRs .set noat - sw $0,(mipsreg_regs+0*4)(sp) - sw $1,(mipsreg_regs+1*4)(sp) - sw $2,(mipsreg_regs+2*4)(sp) - sw $3,(mipsreg_regs+3*4)(sp) - sw $4,(mipsreg_regs+4*4)(sp) - sw $5,(mipsreg_regs+5*4)(sp) - sw $6,(mipsreg_regs+6*4)(sp) - sw $7,(mipsreg_regs+7*4)(sp) - sw $8,(mipsreg_regs+8*4)(sp) - sw $9,(mipsreg_regs+9*4)(sp) - sw $10,(mipsreg_regs+10*4)(sp) - sw $11,(mipsreg_regs+11*4)(sp) - sw $12,(mipsreg_regs+12*4)(sp) - sw $13,(mipsreg_regs+13*4)(sp) - sw $14,(mipsreg_regs+14*4)(sp) - sw $15,(mipsreg_regs+15*4)(sp) - sw $16,(mipsreg_regs+16*4)(sp) - sw $17,(mipsreg_regs+17*4)(sp) - sw $18,(mipsreg_regs+18*4)(sp) - sw $19,(mipsreg_regs+19*4)(sp) - sw $20,(mipsreg_regs+20*4)(sp) - sw $21,(mipsreg_regs+21*4)(sp) - sw $22,(mipsreg_regs+22*4)(sp) - sw $23,(mipsreg_regs+23*4)(sp) - sw $24,(mipsreg_regs+24*4)(sp) - sw $25,(mipsreg_regs+25*4)(sp) -# sw $26,(mipsreg_regs+26*4)(sp) # == K0 -# sw $27,(mipsreg_regs+27*4)(sp) # == K1 - sw $28,(mipsreg_regs+28*4)(sp) # == GP -# sw $29,(mipsreg_regs+29*4)(sp) # == SP - sw $30,(mipsreg_regs+30*4)(sp) # == FP - sw $31,(mipsreg_regs+31*4)(sp) # == RA + sgpr 0,sp + sgpr 1,sp + sgpr 2,sp + sgpr 3,sp + sgpr 4,sp + sgpr 5,sp + sgpr 6,sp + sgpr 7,sp + sgpr 8,sp + sgpr 9,sp + sgpr 10,sp + sgpr 11,sp + sgpr 12,sp + sgpr 13,sp + sgpr 14,sp + sgpr 15,sp + sgpr 16,sp + sgpr 17,sp + sgpr 18,sp + sgpr 19,sp + sgpr 20,sp + sgpr 21,sp + sgpr 22,sp + sgpr 23,sp + sgpr 24,sp + sgpr 25,sp +# sgpr 26,sp # == K0 +# sgpr 27,sp # == K1 + sgpr 28,sp # == GP +# sgpr 29,sp # == SP + sgpr 30,sp # == FP + sgpr 31,sp # == RA .set at mfhi a0 mflo a1 - sw a0,mipsreg_hi(sp) - sw a1,mipsreg_lo(sp) + shi a0,sp + slo a1,sp # K1 contains original SP - sw k1,(mipsreg_regs+29*4)(sp) # store in reg dump + ssp k1,sp # store in reg dump mfc0 t1,status mfc0 t2,cachectrl @@ -611,8 +611,8 @@ restore_state: hal_fpu_load sp lw t0,mipsreg_cachectrl(sp) - lw t1,mipsreg_hi(sp) - lw t2,mipsreg_lo(sp) + lhi t1,sp + llo t2,sp mtc0 t0,cachectrl mthi t1 @@ -620,42 +620,42 @@ restore_state: # load GPRs .set noat -# lw $0,(mipsreg_regs+0*4)(sp) - lw $1,(mipsreg_regs+1*4)(sp) - lw $2,(mipsreg_regs+2*4)(sp) - lw $3,(mipsreg_regs+3*4)(sp) - lw $4,(mipsreg_regs+4*4)(sp) - lw $5,(mipsreg_regs+5*4)(sp) - lw $6,(mipsreg_regs+6*4)(sp) - lw $7,(mipsreg_regs+7*4)(sp) - lw $8,(mipsreg_regs+8*4)(sp) - lw $9,(mipsreg_regs+9*4)(sp) - lw $10,(mipsreg_regs+10*4)(sp) - lw $11,(mipsreg_regs+11*4)(sp) - lw $12,(mipsreg_regs+12*4)(sp) - lw $13,(mipsreg_regs+13*4)(sp) - lw $14,(mipsreg_regs+14*4)(sp) - lw $15,(mipsreg_regs+15*4)(sp) - lw $16,(mipsreg_regs+16*4)(sp) - lw $17,(mipsreg_regs+17*4)(sp) - lw $18,(mipsreg_regs+18*4)(sp) - lw $19,(mipsreg_regs+19*4)(sp) - lw $20,(mipsreg_regs+20*4)(sp) - lw $21,(mipsreg_regs+21*4)(sp) - lw $22,(mipsreg_regs+22*4)(sp) - lw $23,(mipsreg_regs+23*4)(sp) - lw $24,(mipsreg_regs+24*4)(sp) - lw $25,(mipsreg_regs+25*4)(sp) -# lw $26,(mipsreg_regs+26*4)(sp) # == K0 -# lw $27,(mipsreg_regs+27*4)(sp) # == K1 - lw $28,(mipsreg_regs+28*4)(sp) # == GP -# lw $29,(mipsreg_regs+29*4)(sp) # == SP - lw $30,(mipsreg_regs+30*4)(sp) # == FP - lw $31,(mipsreg_regs+31*4)(sp) # == RA +# lgpr 0,sp + lgpr 1,sp + lgpr 2,sp + lgpr 3,sp + lgpr 4,sp + lgpr 5,sp + lgpr 6,sp + lgpr 7,sp + lgpr 8,sp + lgpr 9,sp + lgpr 10,sp + lgpr 11,sp + lgpr 12,sp + lgpr 13,sp + lgpr 14,sp + lgpr 15,sp + lgpr 16,sp + lgpr 17,sp + lgpr 18,sp + lgpr 19,sp + lgpr 20,sp + lgpr 21,sp + lgpr 22,sp + lgpr 23,sp + lgpr 24,sp + lgpr 25,sp +# lgpr 26,sp # == K0 +# lgpr 27,sp # == K1 + lgpr 28,sp # == GP +# lgpr 29,sp # == SP + lgpr 30,sp # == FP + lgpr 31,sp # == RA .set at -#if defined(CYG_HAL_USE_ROM_MONITOR_CYGMON) +#if defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon) # If we have a Cygmon that wants to listen to network interrupts, then # the return code from the earlier call to hal_default_isr() will @@ -685,7 +685,7 @@ restore_state: #endif lw k0,mipsreg_pc(sp) # K0 = return PC lw k1,mipsreg_sr(sp) # K1 = saved SR - lw sp,(mipsreg_regs+29*4)(sp) # load SP + lsp sp,sp # load SP # Invoke CPU specific mechanism for returning from this # exception
--- a/packages/hal/mips/jmr3904/current/ChangeLog +++ b/packages/hal/mips/jmr3904/current/ChangeLog @@ -1,3 +1,16 @@ +2000-01-24 Jesper Skov <jskov@cygnus.co.uk> + + * include/plf_stub.h: Include correct hal/platform header. + +1999-12-21 Jonathan Larmour <jlarmour@cygnus.co.uk> + + * src/plf_misc.c (hal_platform_init): Rename + CYG_HAL_USE_ROM_MONITOR_CYGMON -> CYGSEM_HAL_USE_ROM_MONITOR_CygMon + (cyg_hal_user_break): Likewise. Also rationalize a little. + + * include/platform.inc: Rename CYG_HAL_USE_ROM_MONITOR -> + CYGSEM_HAL_USE_ROM_MONITOR + 1999-11-25 Gary Thomas <gthomas@cygnus.co.uk> * include/pkgconf/mlt_mips_tx39_jmr3904_rom.h:
--- a/packages/hal/mips/jmr3904/current/include/platform.inc +++ b/packages/hal/mips/jmr3904/current/include/platform.inc @@ -55,7 +55,7 @@ #if defined(CYG_HAL_STARTUP_ROM) || \ ( defined(CYG_HAL_STARTUP_RAM) && \ - !defined(CYG_HAL_USE_ROM_MONITOR)) + !defined(CYGSEM_HAL_USE_ROM_MONITOR)) # If we are starting up from ROM, or we are starting in # RAM and NOT using a ROM monitor, initialize the VSR table. @@ -85,7 +85,7 @@ sw a1,33*4(a3) .endm -#elif defined(CYG_HAL_STARTUP_RAM) && defined(CYG_HAL_USE_ROM_MONITOR) +#elif defined(CYG_HAL_STARTUP_RAM) && defined(CYGSEM_HAL_USE_ROM_MONITOR) # Initialize the VSR table entries # We only take control of the interrupt vector, @@ -116,7 +116,7 @@ #if defined(CYG_HAL_MIPS_SIM) || \ ( defined(CYG_HAL_MIPS_TX3904) && \ defined(CYG_HAL_STARTUP_RAM) && \ - !defined(CYG_HAL_USE_ROM_MONITOR) \ + !defined(CYGSEM_HAL_USE_ROM_MONITOR) \ ) ## VSR table defined in linker script
--- a/packages/hal/mips/jmr3904/current/include/plf_stub.h +++ b/packages/hal/mips/jmr3904/current/include/plf_stub.h @@ -44,7 +44,7 @@ //============================================================================= #include <pkgconf/hal.h> -#include <pkgconf/hal_tx39_jmr3904.h> +#include <pkgconf/hal_mips_tx39_jmr3904.h> #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
--- a/packages/hal/mips/jmr3904/current/src/plf_misc.c +++ b/packages/hal/mips/jmr3904/current/src/plf_misc.c @@ -85,8 +85,7 @@ void hal_platform_init(void) #endif #if defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT) && \ - defined(CYG_HAL_USE_ROM_MONITOR) && \ - defined(CYG_HAL_USE_ROM_MONITOR_CYGMON) + defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon) { patch_dbg_syscalls( (void *)(&hal_vsr_table[0]) ); } @@ -108,14 +107,11 @@ cyg_bool cyg_hal_is_break(char *buf, int void cyg_hal_user_break( CYG_ADDRWORD *regs ) { -#if defined(CYG_HAL_USE_ROM_MONITOR) && defined(CYG_HAL_USE_ROM_MONITOR_CYGMON) +#if defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon) // The following code should be at the very start of this function so // that it can access the RA register before it is saved and reused. register CYG_WORD32 ra; asm volatile ( "move %0,$31;" : "=r" (ra) ); -#endif - -#if defined(CYG_HAL_USE_ROM_MONITOR) && defined(CYG_HAL_USE_ROM_MONITOR_CYGMON) { typedef void install_bpt_fn(void *epc);
--- a/packages/hal/mips/tx39/current/ChangeLog +++ b/packages/hal/mips/tx39/current/ChangeLog @@ -1,3 +1,13 @@ +1999-12-21 Jonathan Larmour <jlarmour@cygnus.co.uk> + + * include/var_arch.h: Rename CYG_HAL_USE_ROM_MONITOR_CYGMON -> + CYGSEM_HAL_USE_ROM_MONITOR_CygMon + + * src/hal_diag.c: Likewise. Also CYG_HAL_USE_ROM_MONITOR -> + CYGSEM_HAL_USE_ROM_MONITOR throughout + + * include/pkgconf/hal_mips_tx39.h: Fix typo + 1999-10-26 Nick Garnett <nickg@cygnus.co.uk> * include/variant.inc: Added implementations of hal_intc_translate
--- a/packages/hal/mips/tx39/current/include/pkgconf/hal_mips_tx39.h +++ b/packages/hal/mips/tx39/current/include/pkgconf/hal_mips_tx39.h @@ -65,7 +65,7 @@ parent CYGPKG_HAL_MIPS_TX39 type radio description " - The TMPR3904F microprocessor. This is an emedded part that in + The TMPR3904F microprocessor. This is an embedded part that in addition to the TX39 processor core has built in peripherals such as memory controllers, DMA controllers, serial ports and timers/counters."
--- a/packages/hal/mips/tx39/current/include/var_arch.h +++ b/packages/hal/mips/tx39/current/include/var_arch.h @@ -47,7 +47,7 @@ #include <pkgconf/hal.h> #include <cyg/infra/cyg_type.h> -#ifdef CYG_HAL_USE_ROM_MONITOR_CYGMON +#ifdef CYGSEM_HAL_USE_ROM_MONITOR_CygMon externC int hal_diag_irq_check(int vector);
--- a/packages/hal/mips/tx39/current/src/hal_diag.c +++ b/packages/hal/mips/tx39/current/src/hal_diag.c @@ -57,7 +57,7 @@ //#define CYG_KERNEL_DIAG_LCD #define CYG_KERNEL_DIAG_SERIAL0 // For ROM start but see immediately below: -#if defined(CYG_HAL_USE_ROM_MONITOR_CYGMON) +#if defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon) #undef CYG_KERNEL_DIAG_SERIAL0 #undef CYG_KERNEL_DIAG_LCD #define CYG_KERNEL_DIAG_CYGMON @@ -107,7 +107,7 @@ void hal_diag_led(int x) void hal_diag_init() { -#if defined(CYG_HAL_USE_ROM_MONITOR) +#if defined(CYGSEM_HAL_USE_ROM_MONITOR) // If we are using the ROM monitor, it has already // initialized the serial line. #else @@ -201,7 +201,7 @@ void hal_diag_write_char(char c) #endif { #ifdef CYG_KERNEL_DIAG_GDB -#if 0 //defined(CYG_HAL_USE_ROM_MONITOR) +#if 0 //defined(CYGSEM_HAL_USE_ROM_MONITOR) typedef void rom_write_fn(char c); rom_write_fn *fn = ((rom_write_fn **)0x80000100)[63]; @@ -287,7 +287,7 @@ void hal_diag_read_char(char *c) { for(;;) { -#if defined(CYG_KERNEL_DIAG_GDB) && defined(CYG_HAL_USE_ROM_MONITOR) +#if defined(CYG_KERNEL_DIAG_GDB) && defined(CYGSEM_HAL_USE_ROM_MONITOR) typedef void rom_read_fn(char *c); rom_read_fn *fn = ((rom_read_fn **)0x80000100)[62]; @@ -307,7 +307,7 @@ void hal_diag_read_char(char *c) breakpoint(); continue; } -#elif defined(CYG_HAL_USE_ROM_MONITOR) +#elif defined(CYGSEM_HAL_USE_ROM_MONITOR) if( *c == 3 ) { // Ctrl-C: breakpoint.
--- a/packages/hal/mn10300/am31/current/ChangeLog +++ b/packages/hal/mn10300/am31/current/ChangeLog @@ -1,3 +1,9 @@ +1999-12-21 Jonathan Larmour <jlarmour@cygnus.co.uk> + + * include/variant.inc: Rename CYG_HAL_USE_ROM_MONITOR_CYGMON -> + CYGSEM_HAL_USE_ROM_MONITOR_CygMon + Rename CYG_HAL_USE_ROM_MONITOR -> CYGSEM_HAL_USE_ROM_MONITOR + 1999-10-06 Jonathan Larmour <jlarmour@cygnus.co.uk> * src/PKGconf.mak: Don't create extras.o here any more
--- a/packages/hal/mn10300/am31/current/include/variant.inc +++ b/packages/hal/mn10300/am31/current/include/variant.inc @@ -283,7 +283,7 @@ led_foo3: .byte 0x00 mov d0,(0,a0) mov d0,(4,a0) mov d0,(8,a0) -#ifndef CYG_HAL_USE_ROM_MONITOR_CYGMON +#ifndef CYGSEM_HAL_USE_ROM_MONITOR_CygMon # When using Cygmon, leave level 3 for GDB # Ctrl-C interrupts. mov d0,(12,a0) @@ -304,7 +304,7 @@ led_foo3: .byte 0x00 #if !(defined(CYG_HAL_STARTUP_ROM) || \ defined(CYGPKG_HAL_MN10300_AM31_SIM) || \ - !defined(CYG_HAL_USE_ROM_MONITOR)) + !defined(CYGSEM_HAL_USE_ROM_MONITOR)) #define CYG_HAL_MN10300_VSR_TABLE_DEFINED
--- a/packages/hal/mn10300/stdeval1/current/ChangeLog +++ b/packages/hal/mn10300/stdeval1/current/ChangeLog @@ -1,3 +1,13 @@ +1999-12-21 Jonathan Larmour <jlarmour@cygnus.co.uk> + + * src/plf_misc.c (hal_platform_init): Rename + CYG_HAL_USE_ROM_MONITOR_CYGMON -> CYGSEM_HAL_USE_ROM_MONITOR_CygMon + (cyg_hal_user_break): Rename CYG_HAL_USE_ROM_MONITOR_GDB_STUBS -> + CYGSEM_HAL_USE_ROM_MONITOR_GDB_stubs + + * src/hal_diag.c: Likewise. Rename CYG_HAL_USE_ROM_MONITOR_SLOAD + -> CYGSEM_HAL_USE_ROM_MONITOR_Sload throughout + 1999-11-25 Gary Thomas <gthomas@cygnus.co.uk> * include/pkgconf/mlt_mn10300_am31_stdeval1_rom.h:
--- a/packages/hal/mn10300/stdeval1/current/src/hal_diag.c +++ b/packages/hal/mn10300/stdeval1/current/src/hal_diag.c @@ -64,7 +64,7 @@ # if defined(CYG_HAL_STARTUP_RAM) -# if defined(CYG_HAL_USE_ROM_MONITOR_CYGMON) +# if defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon) // If loaded into RAM via CYGMON we diag via // serial 2 using GDB protocol @@ -72,14 +72,14 @@ # define CYG_KERNEL_DIAG_SERIAL2 # define CYG_KERNEL_DIAG_GDB -# elif defined(CYG_HAL_USE_ROM_MONITOR_SLOAD) +# elif defined(CYGSEM_HAL_USE_ROM_MONITOR_Sload) // If loaded into RAM via SLOAD we diag via // serial 1 # define CYG_KERNEL_DIAG_SERIAL1 -# elif defined(CYG_HAL_USE_ROM_MONITOR_GDB_STUBS) +# elif defined(CYGSEM_HAL_USE_ROM_MONITOR_GDB_stubs) // If loaded into RAM via GDB STUB ROM we diag via // serial 1 using GDB protocol @@ -87,7 +87,7 @@ # define CYG_KERNEL_DIAG_SERIAL1 # define CYG_KERNEL_DIAG_GDB -# endif // defined(CYG_HAL_USE_ROM_MONITOR_CYGMON) +# endif // defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon) # elif defined(CYG_HAL_STARTUP_ROM) @@ -335,7 +335,7 @@ void led(int x) void hal_diag_init_serial2(void) { -#if !defined(CYG_HAL_USE_ROM_MONITOR_CYGMON) +#if !defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon) // 16 and 22 translate to 38400 baud. *TIMER2_BR = 16;
--- a/packages/hal/mn10300/stdeval1/current/src/plf_misc.c +++ b/packages/hal/mn10300/stdeval1/current/src/plf_misc.c @@ -67,8 +67,7 @@ void hal_platform_init(void) #if defined(CYGPKG_KERNEL) && \ defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT) && \ - defined(CYG_HAL_USE_ROM_MONITOR) && \ - defined(CYG_HAL_USE_ROM_MONITOR_CYGMON) + defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon) { extern CYG_ADDRESS hal_virtual_vector_table[32]; extern void patch_dbg_syscalls(void * vector); @@ -92,7 +91,7 @@ cyg_bool cyg_hal_is_break(char *buf, int void cyg_hal_user_break( CYG_ADDRWORD *regs ) { -#if defined(CYG_HAL_USE_ROM_MONITOR) && defined(CYG_HAL_USE_ROM_MONITOR_GDB_STUBS) +#if defined(CYGSEM_HAL_USE_ROM_MONITOR_GDB_stubs) { extern CYG_ADDRESS hal_virtual_vector_table[64];
--- a/packages/hal/powerpc/arch/current/ChangeLog +++ b/packages/hal/powerpc/arch/current/ChangeLog @@ -1,3 +1,8 @@ +2000-01-24 Jesper Skov <jskov@cygnus.co.uk> + + * src/hal_misc.c: Depend on CYGSEM_HAL_ROM_MONITOR instead of + CYG_HAL_ROM_MONITOR. + 1999-09-28 Jesper Skov <jskov@cygnus.co.uk> * tests/intr0.c: Added some more debug output.
--- a/packages/hal/powerpc/arch/current/src/hal_misc.c +++ b/packages/hal/powerpc/arch/current/src/hal_misc.c @@ -478,7 +478,7 @@ externC void hal_MMU_init (void) #endif #ifdef CYGPKG_HAL_POWERPC_MBX // Enable all caches for MBX860 -# ifndef CYG_HAL_ROM_MONITOR // unless we are making a stub rom +# ifndef CYGSEM_HAL_ROM_MONITOR // unless we are making a stub rom # define CYGPRI_INIT_CACHES 1 # define CYGPRI_ENABLE_CACHES 1 # endif
--- a/packages/hal/powerpc/mbx/current/ChangeLog +++ b/packages/hal/powerpc/mbx/current/ChangeLog @@ -1,3 +1,7 @@ +2000-01-24 Jesper Skov <jskov@cygnus.co.uk> + * src/mbx.S: Depend on CYGSEM_HAL_ROM_MONITOR instead of + CYG_HAL_ROM_MONITOR. + 1999-11-25 Gary Thomas <gthomas@cygnus.co.uk> * include/pkgconf/mlt_powerpc_mbx_rom.h:
--- a/packages/hal/powerpc/mbx/current/src/mbx.S +++ b/packages/hal/powerpc/mbx/current/src/mbx.S @@ -71,7 +71,7 @@ # define CYGPRI_DO_PROGRAM_UPMS #endif -#if defined(CYGPRI_RAM_START_PROGRAMS_UPMS) && defined(CYG_HAL_ROM_MONITOR) +#if defined(CYGPRI_RAM_START_PROGRAMS_UPMS) && defined(CYGSEM_HAL_ROM_MONITOR) /* use old tables in a StubROM build iff RAM start will reprogram them */ # define CYGPRI_USE_OLD_UPM_TABLES #endif @@ -558,7 +558,7 @@ FUNC_END( hal_hardware_init ) #else // !CYGPRI_USE_OLD_UPM_TABLES: use the NEW TABLES // for RAM startup or ROM application when NOT making a stub rom, - // ie. CYG_HAL_ROM_MONITOR not defined. + // ie. CYGSEM_HAL_ROM_MONITOR not defined. #ifdef __40MHZ /* UPM contents for 40MHz clk. DRAM: EDO,4K,60ns */ @@ -611,7 +611,7 @@ FUNC_END( hal_hardware_init ) .long 0xffffc007, 0xffffc007, 0xffffc007, 0xffffc007 #endif #endif // OLD/NEW TABLES == CYGPRI_USE_OLD_UPM_TABLES or not. - // depending on CYG_HAL_ROM_MONITOR and whether RAM + // depending on CYGSEM_HAL_ROM_MONITOR and whether RAM // start re-initializes. __upmtbl_end:
--- a/packages/io/serial/current/ChangeLog +++ b/packages/io/serial/current/ChangeLog @@ -1,3 +1,32 @@ +2000-01-17 Gary Thomas <gthomas@cygnus.co.uk> + + * src/common/tty.c (tty_read): Avoid echoing "backspace/erase" at + start of line. + +2000-01-05 Gary Thomas <gthomas@cygnus.co.uk> + + * src/common/serial.c (serial_write): Avoid potential deadlock if + transmit start actually sends enough characters to signal cond wait. + +2000-01-03 Gary Thomas <gthomas@cygnus.co.uk> + + * include/serial.h: Fix namespace pollution - + serial_devio => cyg_io_serial_devio + serial_callbacks => cyg_io_serial_callbacks + + * src/mips/tx3904_serial.c: + * src/mn10300/mn10300_serial.c: + * src/powerpc/quicc_smc_serial.c: + * src/powerpc/cogent_serial_with_ints.c: + * src/sparclite/sleb_sdtr.c: + * src/arm/aeb_serial.c: + * src/arm/pid_serial_with_ints.c: + * src/arm/edb7xxx_serial.c: + * src/arm/cma230_serial.c: + * src/common/haldiag.c: + * src/common/serial.c: Fix namespace pollution - + serial_devio => cyg_io_serial_devio + 1999-12-06 Gary Thomas <gthomas@cygnus.co.uk> * src/arm/pid_serial_with_ints.c (pid_serial_DSR): Add loop to handle
--- a/packages/io/serial/current/include/serial.h +++ b/packages/io/serial/current/include/serial.h @@ -69,7 +69,7 @@ serial_callbacks_t _l = { _rcv_char \ }; -extern serial_callbacks_t serial_callbacks; +extern serial_callbacks_t cyg_io_serial_callbacks; typedef struct { unsigned char *data; @@ -105,7 +105,7 @@ struct serial_channel { _baud, _stop, _parity, _word_length, _flags) \ serial_channel _l = { \ &_funs, \ - &serial_callbacks, \ + &cyg_io_serial_callbacks, \ &(_dev_priv), \ CYG_SERIAL_INFO_INIT(_baud, _stop, _parity, _word_length, _flags), \ }; @@ -118,7 +118,7 @@ serial_channel _l = { _in_buf, _in_buflen) \ serial_channel _l = { \ &_funs, \ - &serial_callbacks, \ + &cyg_io_serial_callbacks, \ &(_dev_priv), \ CYG_SERIAL_INFO_INIT(_baud, _stop, _parity, _word_length, _flags), \ false, \ @@ -149,6 +149,6 @@ serial_funs _l = { _stop_xmit \ }; -extern cyg_devio_table_t serial_devio; +extern cyg_devio_table_t cyg_io_serial_devio; #endif // CYGONCE_SERIAL_H
--- a/packages/io/serial/current/src/arm/aeb_serial.c +++ b/packages/io/serial/current/src/arm/aeb_serial.c @@ -113,7 +113,7 @@ static SERIAL_CHANNEL(aeb_serial_channel DEVTAB_ENTRY(aeb_serial_io0, CYGDAT_IO_SERIAL_ARM_AEB_SERIAL0_NAME, 0, // Does not depend on a lower level interface - &serial_devio, + &cyg_io_serial_devio, aeb_serial_init, aeb_serial_lookup, // Serial driver may need initializing &aeb_serial_channel0 @@ -153,7 +153,7 @@ static SERIAL_CHANNEL(aeb_serial_channel DEVTAB_ENTRY(aeb_serial_io1, CYGDAT_IO_SERIAL_ARM_AEB_SERIAL1_NAME, 0, // Does not depend on a lower level interface - &serial_devio, + &cyg_io_serial_devio, aeb_serial_init, aeb_serial_lookup, // Serial driver may need initializing &aeb_serial_channel1
--- a/packages/io/serial/current/src/arm/cma230_serial.c +++ b/packages/io/serial/current/src/arm/cma230_serial.c @@ -114,7 +114,7 @@ static SERIAL_CHANNEL(cma230_serial_chan DEVTAB_ENTRY(cma230_serial_io0, CYGDAT_IO_SERIAL_ARM_CMA230_SERIAL_A_NAME, 0, // Does not depend on a lower level interface - &serial_devio, + &cyg_io_serial_devio, cma230_serial_init, cma230_serial_lookup, // Serial driver may need initializing &cma230_serial_channel0 @@ -154,7 +154,7 @@ static SERIAL_CHANNEL(cma230_serial_chan DEVTAB_ENTRY(cma230_serial_io1, CYGDAT_IO_SERIAL_ARM_CMA230_SERIAL_B_NAME, 0, // Does not depend on a lower level interface - &serial_devio, + &cyg_io_serial_devio, cma230_serial_init, cma230_serial_lookup, // Serial driver may need initializing &cma230_serial_channel1
--- a/packages/io/serial/current/src/arm/edb7xxx_serial.c +++ b/packages/io/serial/current/src/arm/edb7xxx_serial.c @@ -132,7 +132,7 @@ static SERIAL_CHANNEL(edb7xxx_serial_cha DEVTAB_ENTRY(edb7xxx_serial_io1, CYGDAT_IO_SERIAL_ARM_EDB7XXX_SERIAL1_NAME, 0, // Does not depend on a lower level interface - &serial_devio, + &cyg_io_serial_devio, edb7xxx_serial_init, edb7xxx_serial_lookup, // Serial driver may need initializing &edb7xxx_serial_channel1 @@ -177,7 +177,7 @@ static SERIAL_CHANNEL(edb7xxx_serial_cha DEVTAB_ENTRY(edb7xxx_serial_io2, CYGDAT_IO_SERIAL_ARM_EDB7XXX_SERIAL2_NAME, 0, // Does not depend on a lower level interface - &serial_devio, + &cyg_io_serial_devio, edb7xxx_serial_init, edb7xxx_serial_lookup, // Serial driver may need initializing &edb7xxx_serial_channel2
--- a/packages/io/serial/current/src/arm/pid_serial_with_ints.c +++ b/packages/io/serial/current/src/arm/pid_serial_with_ints.c @@ -111,7 +111,7 @@ static SERIAL_CHANNEL(pid_serial_channel DEVTAB_ENTRY(pid_serial_io0, CYGDAT_IO_SERIAL_ARM_PID_SERIAL0_NAME, 0, // Does not depend on a lower level interface - &serial_devio, + &cyg_io_serial_devio, pid_serial_init, pid_serial_lookup, // Serial driver may need initializing &pid_serial_channel0 @@ -150,7 +150,7 @@ static SERIAL_CHANNEL(pid_serial_channel DEVTAB_ENTRY(pid_serial_io1, CYGDAT_IO_SERIAL_ARM_PID_SERIAL1_NAME, 0, // Does not depend on a lower level interface - &serial_devio, + &cyg_io_serial_devio, pid_serial_init, pid_serial_lookup, // Serial driver may need initializing &pid_serial_channel1
--- a/packages/io/serial/current/src/common/haldiag.c +++ b/packages/io/serial/current/src/common/haldiag.c @@ -62,7 +62,7 @@ static SERIAL_FUNS(haldiag_funs, ); static int _no_data; -SERIAL_CHANNEL(haldiag_channel0, +static SERIAL_CHANNEL(haldiag_channel0, haldiag_funs, _no_data, CYG_SERIAL_BAUD_DEFAULT, @@ -74,7 +74,7 @@ SERIAL_CHANNEL(haldiag_channel0, DEVTAB_ENTRY(haldiag_io0, "/dev/haldiag", 0, // Does not depend on a lower level interface - &serial_devio, + &cyg_io_serial_devio, haldiag_init, 0, // No initialization/lookup needed &haldiag_channel0);
--- a/packages/io/serial/current/src/common/serial.c +++ b/packages/io/serial/current/src/common/serial.c @@ -50,7 +50,7 @@ static Cyg_ErrNo serial_read(cyg_io_hand static Cyg_ErrNo serial_get_config(cyg_io_handle_t handle, cyg_uint32 key, void *buf, cyg_uint32 *len); static Cyg_ErrNo serial_set_config(cyg_io_handle_t handle, cyg_uint32 key, const void *buf, cyg_uint32 *len); -DEVIO_TABLE(serial_devio, +DEVIO_TABLE(cyg_io_serial_devio, serial_write, serial_read, serial_get_config, @@ -60,7 +60,7 @@ DEVIO_TABLE(serial_devio, static void serial_init(serial_channel *chan); static void serial_xmt_char(serial_channel *chan); static void serial_rcv_char(serial_channel *chan, unsigned char c); -SERIAL_CALLBACKS(serial_callbacks, +SERIAL_CALLBACKS(cyg_io_serial_callbacks, serial_init, serial_xmt_char, serial_rcv_char); @@ -121,9 +121,12 @@ serial_write(cyg_io_handle_t handle, con cbuf->waiting = true; // Buffer full - wait for space (funs->start_xmit)(chan); // Make sure xmit is running - cbuf->pending += size; // Have this much more to send [eventually] - cyg_drv_cond_wait(&cbuf->wait); - cbuf->pending -= size; + if (cbuf->waiting) { + // Note: 'start_xmit' may have obviated the need to wait :-) + cbuf->pending += size; // Have this much more to send [eventually] + cyg_drv_cond_wait(&cbuf->wait); + cbuf->pending -= size; + } if (cbuf->abort) { // Give up! cbuf->abort = false;
--- a/packages/io/serial/current/src/common/tty.c +++ b/packages/io/serial/current/src/common/tty.c @@ -208,8 +208,9 @@ tty_read(cyg_io_handle_t handle, void *_ if ((priv->dev_info.tty_in_flags & CYG_TTY_IN_FLAGS_BINARY) == 0) { if ((c == '\b') || (c == 0x7F)) { size -= 2; // erase one character + 'backspace' char - if (size < 0) size = 0; - if (priv->dev_info.tty_in_flags & CYG_TTY_IN_FLAGS_ECHO) { + if (size < 0) { + size = 0; + } else if (priv->dev_info.tty_in_flags & CYG_TTY_IN_FLAGS_ECHO) { clen = 3; cyg_io_write(chan, "\b \b", &clen); }
--- a/packages/io/serial/current/src/mips/tx3904_serial.c +++ b/packages/io/serial/current/src/mips/tx3904_serial.c @@ -325,7 +325,7 @@ static SERIAL_CHANNEL(tx3904_serial_chan DEVTAB_ENTRY(tx3904_serial_io0, CYGDAT_IO_SERIAL_TX39_JMR3904_SERIAL0_NAME, 0, // Does not depend on a lower level interface - &serial_devio, + &cyg_io_serial_devio, tx3904_serial_init, tx3904_serial_lookup, // Serial driver may need initializing &tx3904_serial_channel0 @@ -336,7 +336,7 @@ DEVTAB_ENTRY(tx3904_serial_io0, DEVTAB_ENTRY(tx3904_serial_io1, CYGDAT_IO_SERIAL_TX39_JMR3904_SERIAL1_NAME, 0, // Does not depend on a lower level interface - &serial_devio, + &cyg_io_serial_devio, tx3904_serial_init, tx3904_serial_lookup, // Serial driver may need initializing &tx3904_serial_channel1
--- a/packages/io/serial/current/src/mn10300/mn10300_serial.c +++ b/packages/io/serial/current/src/mn10300/mn10300_serial.c @@ -452,7 +452,7 @@ static SERIAL_CHANNEL(mn10300_serial_cha DEVTAB_ENTRY(mn10300_serial_io0, CYGDAT_IO_SERIAL_MN10300_SERIAL0_NAME, 0, // Does not depend on a lower level interface - &serial_devio, + &cyg_io_serial_devio, mn10300_serial_init, mn10300_serial_lookup, // Serial driver may need initializing &mn10300_serial_channel0 @@ -464,7 +464,7 @@ DEVTAB_ENTRY(mn10300_serial_io0, DEVTAB_ENTRY(mn10300_serial_io1, CYGDAT_IO_SERIAL_MN10300_SERIAL1_NAME, 0, // Does not depend on a lower level interface - &serial_devio, + &cyg_io_serial_devio, mn10300_serial_init, mn10300_serial_lookup, // Serial driver may need initializing &mn10300_serial_channel1 @@ -475,7 +475,7 @@ DEVTAB_ENTRY(mn10300_serial_io1, DEVTAB_ENTRY(mn10300_serial_io2, CYGDAT_IO_SERIAL_MN10300_SERIAL2_NAME, 0, // Does not depend on a lower level interface - &serial_devio, + &cyg_io_serial_devio, mn10300_serial_init, mn10300_serial_lookup, // Serial driver may need initializing &mn10300_serial_channel2
--- a/packages/io/serial/current/src/powerpc/cogent_serial_with_ints.c +++ b/packages/io/serial/current/src/powerpc/cogent_serial_with_ints.c @@ -130,7 +130,7 @@ static SERIAL_CHANNEL(cogent_serial_chan DEVTAB_ENTRY(cogent_serial_io0, CYGDAT_IO_SERIAL_POWERPC_COGENT_SERIAL_A_NAME, 0, // Does not depend on a lower level interface - &serial_devio, + &cyg_io_serial_devio, cogent_serial_init, cogent_serial_lookup, // Serial driver may need initializing &cogent_serial_channel0 @@ -172,7 +172,7 @@ static SERIAL_CHANNEL(cogent_serial_chan DEVTAB_ENTRY(cogent_serial_io1, CYGDAT_IO_SERIAL_POWERPC_COGENT_SERIAL_B_NAME, 0, // Does not depend on a lower level interface - &serial_devio, + &cyg_io_serial_devio, cogent_serial_init, cogent_serial_lookup, // Serial driver may need initializing &cogent_serial_channel1
--- a/packages/io/serial/current/src/powerpc/quicc_smc_serial.c +++ b/packages/io/serial/current/src/powerpc/quicc_smc_serial.c @@ -157,7 +157,7 @@ static unsigned char quicc_smc1_rxbuf[CY DEVTAB_ENTRY(quicc_smc_serial_io1, CYGDAT_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_NAME, 0, // Does not depend on a lower level interface - &serial_devio, + &cyg_io_serial_devio, quicc_smc_serial_init, quicc_smc_serial_lookup, // Serial driver may need initializing &quicc_smc_serial_channel1 @@ -201,7 +201,7 @@ static unsigned char quicc_smc2_rxbuf[CY DEVTAB_ENTRY(quicc_smc_serial_io2, CYGDAT_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_NAME, 0, // Does not depend on a lower level interface - &serial_devio, + &cyg_io_serial_devio, quicc_smc_serial_init, quicc_smc_serial_lookup, // Serial driver may need initializing &quicc_smc_serial_channel2
--- a/packages/io/serial/current/src/sparclite/sleb_sdtr.c +++ b/packages/io/serial/current/src/sparclite/sleb_sdtr.c @@ -121,7 +121,7 @@ static SERIAL_CHANNEL(sleb_sdtr_channel0 DEVTAB_ENTRY(sleb_sdtr_io0, CYGDAT_IO_SERIAL_SPARCLITE_SLEB_CON1_NAME, 0, // Does not depend on a lower level interface - &serial_devio, + &cyg_io_serial_devio, sleb_sdtr_init, sleb_sdtr_lookup, // Serial driver may need initializing &sleb_sdtr_channel0
--- a/packages/kernel/current/ChangeLog +++ b/packages/kernel/current/ChangeLog @@ -1,3 +1,58 @@ +2000-01-19 Jesper Skov <jskov@cygnus.co.uk> + CR 902054 + * tests/stress_threads.c: Don't assert requested priority = + allocated. Allow some flexibility of handler priorities. + +2000-01-13 Hugo Tyson <hmt@cygnus.co.uk> + + * tests/mutex3.cxx (control_thread): Add a CYG_TEST_INIT(); + Whoops! + +2000-01-11 Hugo Tyson <hmt@cygnus.co.uk> + + * tests/mutex3.cxx: New test case. It tests mutex prio + inheritance - or not - in a multiple thread manner, depending only + on delays and the clock, so it tests that scheduling does the + right thing, rather than simply checking reported priorities. + + * tests/PKGconf.mak: Add new kernel test mutex3, put in to test + RELAY prio inheritance extension. + +2000-01-11 Hugo Tyson <hmt@cygnus.co.uk> + + * include/pkgconf/kernel.h: New config option added, + (CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE_SIMPLE_RELAY). + It is a child of ..._PRIORITY_INHERITANCE_SIMPLE and is really + only there to turn off if you really want the old implementation. + + * src/sync/mutex.cxx (unlock): Add call to + Cyg_SchedThread::relay_priority() when relinquishing the mutex, in + order to relay any raised priority to the new owner. Also count + the mutex we are waiting for as well as those held for correct + recovery in the case of inheriting priority then being killed, for + example. + + * include/sched.hxx (class Cyg_SchedThread::relay_priority): New + member function declared. + + * src/sched/sched.cxx (Cyg_SchedThread::relay_priority): New + member function to implement pass-it-on or "discovered ceiling" + priority inheritance extension to the simple algorithm. Also use + get_current_priority() in Cyg_SchedThread::inherit_priority() to + let this work. + +2000-01-11 Hugo Tyson <hmt@cygnus.co.uk> + + * include/clock.hxx (class Cyg_Counter::counter): make the counter + volatile, otherwise a busy-wait loop for the real time clock to + change never completes. + +1999-12-23 Hugo Tyson <hmt@cygnus.co.uk> + + * src/sched/sched.cxx (inherit_priority): Fix bug; inheriting a + 2nd time would overwrite the saved initial_priority, so + disinheriting had no effect. + 1999-12-13 Jonathan Larmour <jlarmour@cygnus.co.uk> * tests/tm_basic.cxx (run_alarm_tests): Add new measurement of @@ -2491,7 +2546,8 @@ Wed Mar 11 13:18:17 GMT 1998 Chris Prov // September 30, 1998. // // The Initial Developer of the Original Code is Cygnus. Portions created -// by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. All Rights Reserved. +// by Cygnus are Copyright (C) 1998,1999,2000 Cygnus Solutions. +// All Rights Reserved. // ------------------------------------------- // //####COPYRIGHTEND####
--- a/packages/kernel/current/include/clock.hxx +++ b/packages/kernel/current/include/clock.hxx @@ -25,7 +25,8 @@ // September 30, 1998. // // The Initial Developer of the Original Code is Cygnus. Portions created -// by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. All Rights Reserved. +// by Cygnus are Copyright (C) 1998,1999,2000 Cygnus Solutions. +// All Rights Reserved. // ------------------------------------------- // //####COPYRIGHTEND#### @@ -72,7 +73,7 @@ class Cyg_Counter #endif - cyg_tick_count counter; // counter value + volatile cyg_tick_count counter; // counter value cyg_uint32 increment; // increment per tick
--- a/packages/kernel/current/include/pkgconf/kernel.h +++ b/packages/kernel/current/include/pkgconf/kernel.h @@ -24,7 +24,8 @@ // September 30, 1998. // // The Initial Developer of the Original Code is Cygnus. Portions created -// by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. All Rights Reserved. +// by Cygnus are Copyright (C) 1998,1999,2000 Cygnus Solutions. +// All Rights Reserved. // ------------------------------------------- // //####COPYRIGHTEND#### @@ -723,6 +724,18 @@ doc ref/ecos-ref/synchronization.html#MUTEXES } + cdl_option CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE_SIMPLE_RELAY { + display "Relay enhancement to simple mutex priority inheritance" + parent CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE_SIMPLE + description " + This option enables an extension to the simple implementation of + mutex priority inheritance whereby a thread releasing a mutex to a + waiting thread relays its own priority to the new owner if there + are still further threads waiting. This can be viewed as a + discovered priority ceiling." + doc ref/ecos-ref/synchronization.html#MUTEXES + } + cdl_option CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT { display "Message box blocking put support" parent CYGPKG_KERNEL_SYNCH @@ -771,6 +784,7 @@ */ #define CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE_SIMPLE +#define CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE_SIMPLE_RELAY #define CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT #define CYGNUM_KERNEL_SYNCH_MBOX_QUEUE_SIZE 10 #define CYGMFN_KERNEL_SYNCH_CONDVAR_TIMED_WAIT
--- a/packages/kernel/current/include/sched.hxx +++ b/packages/kernel/current/include/sched.hxx @@ -25,7 +25,8 @@ // September 30, 1998. // // The Initial Developer of the Original Code is Cygnus. Portions created -// by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. All Rights Reserved. +// by Cygnus are Copyright (C) 1998,1999,2000 Cygnus Solutions. +// All Rights Reserved. // ------------------------------------------- // //####COPYRIGHTEND#### @@ -166,8 +167,10 @@ public: private: - // For all priority inheritance mechanisms we need to - // keep track of how many mutexes we have locked. + // For all priority inheritance mechanisms we need to keep track of how + // many mutexes we have locked, including one which we are waiting to + // lock, because we can inherit priority while sleeping just prior to + // wakeup. cyg_count32 mutex_count; public: @@ -194,6 +197,10 @@ public: // has higher priority than this. void inherit_priority( Cyg_Thread *thread); + // Relay the priority of the ex-owner thread or from the queue if it + // has a higher priority than ours. + void relay_priority( Cyg_Thread *ex_owner, Cyg_ThreadQueue *pqueue); + // Lose priority inheritance void disinherit_priority();
--- a/packages/kernel/current/src/sched/sched.cxx +++ b/packages/kernel/current/src/sched/sched.cxx @@ -22,7 +22,8 @@ // September 30, 1998. // // The Initial Developer of the Original Code is Cygnus. Portions created -// by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. All Rights Reserved. +// by Cygnus are Copyright (C) 1998,1999,2000 Cygnus Solutions. +// All Rights Reserved. // ------------------------------------------- // //####COPYRIGHTEND#### @@ -313,33 +314,59 @@ void Cyg_SchedThread::inherit_priority( CYG_ASSERT( mutex_count > 0, "Non-positive mutex count"); CYG_ASSERT( self != thread, "Trying to inherit from self!"); - if( thread->get_priority() < priority ) + // Compare with *current* priority in case thread has already + // inherited - for relay case below. + if( thread->get_current_priority() < priority ) { cyg_priority mypri = priority; + cyg_bool already_inherited = priority_inherited; - if( !priority_inherited ) - { - // If this is first inheritance, copy the old pri - // and set inherited flag. We do this after setting the - // pri since set_priority() is inheritance aware. + // If this is first inheritance, copy the old pri + // and set inherited flag. We clear it before setting the + // pri since set_priority() is inheritance aware. + // This is called with the sched locked, so no race conditions. - self->set_priority( thread->get_priority() ); - priority_inherited = true, + priority_inherited = false; // so that set_prio DTRT + + self->set_priority( thread->get_current_priority() ); + + if( !already_inherited ) original_priority = mypri; - } - else - { - // Already in inherited state, and new pri is higher - // than old. Just change the pri. - - self->set_priority( thread->get_priority() ); - } + + priority_inherited = true; // regardless, because it is now + } #endif } // ------------------------------------------------------------------------- +// Inherit the priority of the ex-owner thread or from the queue if it +// has a higher priority than ours. + +void Cyg_SchedThread::relay_priority( Cyg_Thread *ex_owner, Cyg_ThreadQueue *pqueue) +{ +#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE_SIMPLE + + // A simple implementation of priority inheritance. + // At its simplest, this member does nothing. + +#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE_SIMPLE_RELAY + + // If there is anyone else waiting, then the *new* owner inherits from + // the current one, since that is a maxima of the others waiting. + // (It's worth not doing if there's nobody waiting to prevent + // unneccessary priority skew.) This could be viewed as a discovered + // priority ceiling. + + if ( !pqueue->empty() ) + inherit_priority( ex_owner ); + +#endif +#endif +} + +// ------------------------------------------------------------------------- // Lose a priority inheritance void Cyg_SchedThread::disinherit_priority() @@ -357,6 +384,13 @@ void Cyg_SchedThread::disinherit_priorit // should be negligible. The most important advantage of this // algorithm is that it is fast and deterministic. + // The simplest algorithm also does not cause a 2nd owner (who waited) + // of a mutex to inherit from 3rd, 4th &c threads that are queueing up + // when it is awoken. That limitation is avoided when + // CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE_SIMPLE_RELAY is also + // enabled, see above, which passes the raised priority from one thread + // to the next along with the mutex, like a relay baton. + Cyg_Thread *self = CYG_CLASSFROMBASE(Cyg_Thread, Cyg_SchedThread, this); @@ -376,7 +410,7 @@ void Cyg_SchedThread::disinherit_priorit #endif } -#endif +#endif // CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE of any kind // ------------------------------------------------------------------------- // EOF sched/sched.cxx
--- a/packages/kernel/current/src/sync/mutex.cxx +++ b/packages/kernel/current/src/sync/mutex.cxx @@ -22,7 +22,8 @@ // September 30, 1998. // // The Initial Developer of the Original Code is Cygnus. Portions created -// by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. All Rights Reserved. +// by Cygnus are Copyright (C) 1998,1999,2000 Cygnus Solutions. +// All Rights Reserved. // ------------------------------------------- // //####COPYRIGHTEND#### @@ -133,6 +134,12 @@ Cyg_Mutex::lock(void) // thread grabbing the mutex between the wakeup in unlock() and // this thread actually starting. +#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE + + self->count_mutex(); + +#endif + while( locked && result ) { CYG_ASSERT( self != owner, "Locking mutex I already own"); @@ -182,14 +189,15 @@ Cyg_Mutex::lock(void) locked = true; owner = self; -#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE - - self->count_mutex(); - -#endif - CYG_INSTRUMENT_MUTEX(LOCKED, this, 0); } +#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE + else + { + self->uncount_mutex(); + self->disinherit_priority(); + } +#endif // Unlock the scheduler and maybe switch threads Cyg_Scheduler::unlock(); @@ -259,6 +267,32 @@ Cyg_Mutex::unlock(void) CYG_ASSERT( locked, "Unlock mutex that is not locked"); CYG_ASSERT( owner == Cyg_Thread::self(), "Unlock mutex I do not own"); + if( !queue.empty() ) { + + // The queue is non-empty, so grab the next + // thread from it and wake it up. + + Cyg_Thread *thread = queue.dequeue(); + + CYG_ASSERTCLASS( thread, "Bad thread pointer"); + +#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE + + // Give the owner-to-be a chance to inherit from the remaining + // queue or the relinquishing thread: + + thread->relay_priority(owner, &queue); + +#endif + + thread->set_wake_reason( Cyg_Thread::DONE ); + + thread->wake(); + + CYG_INSTRUMENT_MUTEX(WAKE, this, thread); + + } + #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE owner->uncount_mutex(); @@ -269,23 +303,6 @@ Cyg_Mutex::unlock(void) locked = false; owner = NULL; - if( !queue.empty() ) { - - // The queue is non-empty, so grab the next - // thread from it and wake it up. - - Cyg_Thread *thread = queue.dequeue(); - - CYG_ASSERTCLASS( thread, "Bad thread pointer"); - - thread->set_wake_reason( Cyg_Thread::DONE ); - - thread->wake(); - - CYG_INSTRUMENT_MUTEX(WAKE, this, thread); - - } - CYG_ASSERTCLASS( this, "Bad this pointer"); // Unlock the scheduler and maybe switch threads
--- a/packages/kernel/current/tests/PKGconf.mak +++ b/packages/kernel/current/tests/PKGconf.mak @@ -22,7 +22,8 @@ # September 30, 1998. # # The Initial Developer of the Original Code is Cygnus. Portions created -# by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. All Rights Reserved. +# by Cygnus are Copyright (C) 1998,1999,2000 Cygnus Solutions. +# All Rights Reserved. # ------------------------------------------- # #####COPYRIGHTEND#### @@ -37,7 +38,7 @@ TESTS := bin_sem0 bin_sem1 bin_sem kclock0 kclock1 kexcept1 kintr0 kmbox1 kmemfix1 kmemvar1 \ kmutex0 kmutex1 ksched1 ksem0 ksem1 kflag0 kflag1 \ kthread0 kthread1 mbox1 memfix1 memfix2 memvar1 memvar2\ - mutex0 mutex1 mutex2 sched1 sync2 sync3 \ + mutex0 mutex1 mutex2 mutex3 sched1 sync2 sync3 \ thread0 thread1 thread2 release kill thread_gdb \ tm_basic dhrystone
new file mode 100644 --- /dev/null +++ b/packages/kernel/current/tests/mutex3.cxx @@ -0,0 +1,562 @@ +//========================================================================== +// +// mutex3.cxx +// +// Mutex test 3 - priority inheritance +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Cygnus eCos Public License +// Version 1.0 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://sourceware.cygnus.com/ecos +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Cygnus Operating System, released +// September 30, 1998. +// +// The Initial Developer of the Original Code is Cygnus. Portions created +// by Cygnus are Copyright (C) 1998,1999,2000 Cygnus Solutions. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-01-06 +// Description: Tests mutex priority inheritance +//####DESCRIPTIONEND#### + +#include <pkgconf/kernel.h> + +#include <cyg/kernel/sched.hxx> // Cyg_Scheduler::start() +#include <cyg/kernel/thread.hxx> // Cyg_Thread + +#include <cyg/kernel/mutex.hxx> + +#include <cyg/infra/testcase.h> + +#include <cyg/kernel/sched.inl> +#include <cyg/kernel/thread.inl> + +#include <cyg/infra/diag.h> // diag_printf + +// ------------------------------------------------------------------------ +// +// These checks should be enough; any other scheduler which has priorities +// should manifest as having no priority inheritance, but otherwise fine, +// so the test should work correctly. + +#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK) && \ + (CYGNUM_KERNEL_SCHED_PRIORITIES > 20) + +// ------------------------------------------------------------------------ +// Management functions +// +// Stolen from testaux.hxx and copied in here because I want to be able to +// reset the world also. + +#define NTHREADS 7 + +static inline void *operator new(size_t size, void *ptr) { return ptr; }; + +#define STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL + +static Cyg_Thread *thread[NTHREADS] = { 0 }; + +typedef CYG_WORD64 CYG_ALIGNMENT_TYPE; + +static CYG_ALIGNMENT_TYPE thread_obj[NTHREADS] [ + (sizeof(Cyg_Thread)+sizeof(CYG_ALIGNMENT_TYPE)-1) + / sizeof(CYG_ALIGNMENT_TYPE) ]; + +static CYG_ALIGNMENT_TYPE stack[NTHREADS] [ + (STACKSIZE+sizeof(CYG_ALIGNMENT_TYPE)-1) + / sizeof(CYG_ALIGNMENT_TYPE) ]; + +static int nthreads = 0; + +static Cyg_Thread *new_thread( cyg_thread_entry *entry, + CYG_ADDRWORD data, + CYG_ADDRWORD priority, + int do_resume ) +{ + CYG_ASSERT(nthreads < NTHREADS, + "Attempt to create more than NTHREADS threads"); + + thread[nthreads] = new( (void *)&thread_obj[nthreads] ) + Cyg_Thread(priority, + entry, data, + NULL, // no name + (CYG_ADDRESS)stack[nthreads], STACKSIZE ); + + if ( do_resume ) + thread[nthreads]->resume(); + + return thread[nthreads++]; +} + + +static void kill_threads( void ) +{ + CYG_ASSERT(nthreads <= NTHREADS, + "More than NTHREADS threads"); + CYG_ASSERT( Cyg_Thread::self() == thread[0], + "kill_threads() not called from thread 0"); + while ( nthreads > 1 ) { + nthreads--; + if ( NULL != thread[nthreads] ) { + thread[nthreads]->kill(); + thread[nthreads]->~Cyg_Thread(); + thread[nthreads] = NULL; + } + } + CYG_ASSERT(nthreads == 1, + "No threads left"); +} + +// ------------------------------------------------------------------------ + +#define DELAYFACTOR 1 // for debugging + +// ------------------------------------------------------------------------ + +static Cyg_Mutex mutex; + +// These are for reporting back to the master thread +volatile int got_it = 0; +volatile int t3ran = 0; +volatile int t3ended = 0; +volatile int extras[4] = {0,0,0,0}; + +volatile int go_flag = 0; // but this one controls thread 3 from thread 2 + +// ------------------------------------------------------------------------ +// 0 to 3 of these run generally to interfere with the other processing, +// to cause multiple prio inheritances, and clashes in any orders. + +static void extra_thread( CYG_ADDRWORD data ) +{ +#define XINFO( z ) \ + do { z[13] = '0' + data; CYG_TEST_INFO( z ); } while ( 0 ) + + static char running[] = "Extra thread Xa running"; + static char exiting[] = "Extra thread Xa exiting"; + static char resumed[] = "Extra thread Xa resumed"; + static char locked[] = "Extra thread Xa locked"; + static char unlocked[] = "Extra thread Xa unlocked"; + + XINFO( running ); + + Cyg_Thread *self = Cyg_Thread::self(); + + self->suspend(); + + XINFO( resumed ); + + mutex.lock(); + + XINFO( locked ); + + mutex.unlock(); + + XINFO( unlocked ); + + extras[ data ] ++; + + XINFO( exiting ); + +} + +// ------------------------------------------------------------------------ + +static void t1( CYG_ADDRWORD data ) +{ + Cyg_Thread *self = Cyg_Thread::self(); + + CYG_TEST_INFO( "Thread 1 running" ); + + self->suspend(); + + mutex.lock(); + + got_it++; + + CYG_TEST_CHECK( 0 == t3ended, "T3 ended prematurely [T1,1]" ); + + mutex.unlock(); + + CYG_TEST_CHECK( 0 == t3ended, "T3 ended prematurely [T1,2]" ); + + // That's all. + + CYG_TEST_INFO( "Thread 1 exit" ); +} + +// ------------------------------------------------------------------------ + +static void t2( CYG_ADDRWORD data ) +{ + Cyg_Thread *self = Cyg_Thread::self(); + int i; + cyg_tick_count then, now; + + + CYG_TEST_INFO( "Thread 2 running" ); + + CYG_TEST_CHECK( 0 == (data & ~0x77), "Bad T2 arg: extra bits" ); + CYG_TEST_CHECK( 0 == (data & (data >> 4)), "Bad T2 arg: overlap" ); + + self->suspend(); + + // depending on our config argument, optionally restart some of the + // extra threads to throw noise into the scheduler: + for ( i = 0; i < 3; i++ ) + if ( (1 << i) & data ) // bits 0-2 control + thread[i+4]->resume(); // made sure extras are thread[4-6] + + self->delay( DELAYFACTOR * 10 ); // let those threads run + + Cyg_Scheduler::lock(); // do this next lot atomically + + go_flag = 1; // unleash thread 3 + thread[1]->resume(); // resume thread 1 + + // depending on our config argument, optionally restart some of the + // extra threads to throw noise into the scheduler at this later point: + for ( i = 4; i < 7; i++ ) + if ( (1 << i) & data ) // bits 4-6 control + thread[i]->resume(); // made sure extras are thread[4-6] + + Cyg_Scheduler::unlock(); // let scheduling proceed + + // Need a delay (but not a CPU yield) to allow t3 to awaken and act on + // the go_flag, otherwise we check these details below too soon. + // Actually, waiting for the clock to tick a couple of times would be + // better, so that is what we will do. Must be a busy-wait. + then = Cyg_Clock::real_time_clock->current_value(); + do { + now = Cyg_Clock::real_time_clock->current_value(); + // Wait longer than the delay in t3 waiting on go_flag + } while ( now < (then + 3) ); + +#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE + CYG_TEST_INFO( "Checking for MUTEX_PRIORITY_INHERITANCE" ); + CYG_TEST_CHECK( 1 == t3ran, "Thread 3 did not run" ); + CYG_TEST_CHECK( 1 == got_it, "Thread 1 did not get the mutex" ); +#else + CYG_TEST_INFO( "Checking for NO mutex_priority_inheritance" ); + CYG_TEST_CHECK( 0 == t3ran, "Thread 3 DID run" ); + CYG_TEST_CHECK( 0 == got_it, "Thread 1 DID get the mutex" ); +#endif + + CYG_TEST_CHECK( 0 == t3ended, "Thread 3 ended prematurely [T2,1]" ); + + self->delay( DELAYFACTOR * 20 ); // let those threads run + + CYG_TEST_CHECK( 1 == t3ran, "Thread 3 did not run" ); + CYG_TEST_CHECK( 1 == got_it, "Thread 1 did not get the mutex" ); + CYG_TEST_CHECK( 1 == t3ended, "Thread 3 has not ended" ); + + for ( i = 0; i < 3; i++ ) + if ( (1 << i) & (data | data >> 4) ) // bits 0-2 and 4-6 control + CYG_TEST_CHECK( 1 == extras[i+1], "Extra thread did not run" ); + else + CYG_TEST_CHECK( 0 == extras[i+1], "Extra thread ran" ); + + CYG_TEST_PASS( "Thread 2 exiting, AOK" ); + // That's all: restart the control thread. + thread[0]->resume(); +} + +// ------------------------------------------------------------------------ + +static void t3( CYG_ADDRWORD data ) +{ + Cyg_Thread *self = Cyg_Thread::self(); + + CYG_TEST_INFO( "Thread 3 running" ); + + mutex.lock(); + + self->delay( DELAYFACTOR * 5 ); // let thread 3a run + + thread[2]->resume(); // resume thread 2 + + while ( 0 == go_flag ) + self->delay(1); // wait until we are told to go + + t3ran ++; // record the fact + + CYG_TEST_CHECK( 0 == got_it, "Thread 1 claims to have got my mutex" ); + + mutex.unlock(); + + t3ended ++; // record that we came back + + CYG_TEST_CHECK( 1 == got_it, "Thread 1 did not get the mutex" ); + + CYG_TEST_INFO( "Thread 3 exit" ); +} + +// ------------------------------------------------------------------------ + +static void control_thread( CYG_ADDRWORD data ) +{ + Cyg_Thread *self = Cyg_Thread::self(); + int i; + + CYG_TEST_INIT(); + CYG_TEST_INFO( "Control Thread running" ); + + // Go through the 27 possibilitied of resuming the extra threads + // 0: not at all + // 1: early in the process + // 2: later on + // which are represented by bits 0-3 and 4-6 resp in the argument to + // thread 2 (none set means no resume at all). + for ( i = 0; i < 27; i++ ) { + static int xx[] = { 0, 1, 16 }; + int j = i % 3; + int k = (i / 3) % 3; + int l = (i / 9) % 3; + + int d = xx[j] | (xx[k]<<1) | (xx[l]<<2) ; + + +#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE + // If the simple scheme plus relay enhancement, or any other + // *complete* scheme, we can run all three ancillary threads no + // problem, so no special action here. + +#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE_SIMPLE +#ifndef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE_SIMPLE_RELAY + // If the simple scheme but no relay enhancement: + if ( k ) // Cannot run thread 2a nor 3a + break; // if no priority relay. +#endif +#endif + +#else + // If no priority inheritance at all, running threads 1a and 2a is + // OK, but not thread 3a; it blocks the world. + if ( l ) // Cannot run thread 3a if no + break; // priority inheritance at all. +#endif + + mutex = Cyg_Mutex(); // Reinitialize this + + got_it = 0; + t3ran = 0; + t3ended = 0; + for ( int z = 0; z < 4; z++ ) extras[z] = 0; + go_flag = 0; + + new_thread( t1, 0, 5, 1 ); // Slot 1 + new_thread( t2, d, 10, 1 ); // Slot 2 + new_thread( t3, 0, 15, 1 ); // Slot 3 + + new_thread( extra_thread, 1, 8, j ); // Slot 4 + new_thread( extra_thread, 2, 12, k ); // Slot 5 + new_thread( extra_thread, 3, 17, l ); // Slot 6 + + { + static char *a[] = { "inactive", "run early", "run late" }; + diag_printf( "\n----- [%2d] New Cycle: 0x%02x, Threads 1a %s, 2a %s, 3a %s -----\n", + i, d, a[j], a[k], a[l] ); + } + + self->suspend(); + + kill_threads(); + mutex.~Cyg_Mutex(); + } + CYG_TEST_EXIT( "Control Thread exit" ); +} + +// ------------------------------------------------------------------------ + +externC void +cyg_user_start( void ) +{ + new_thread( control_thread, 0, 2, 1 ); +} + +#else // CYGVAR_KERNEL_COUNTERS_CLOCK &c + +externC void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_PASS_FINISH("Mutex3 test requires:\n" + "CYGVAR_KERNEL_COUNTERS_CLOCK &&\n" + "(CYGNUM_KERNEL_SCHED_PRIORITIES > 20)\n"); +} +#endif // CYGVAR_KERNEL_COUNTERS_CLOCK &c + + +// ------------------------------------------------------------------------ +// Documentation: enclosed is the design of this test. +// +// It has been carefully constructed so that it does NOT use other kernel +// facilities (aside from delay-task) to test that priority inheritance is +// working, or not, as intended by the configuration. +// +// These notes describe the flow of control in one run of the test with the +// ancillary tasks optionally interspersed. The details of how those extra +// tasks are or are not allowed to run are not described. +// +// +// +// The only change in the test that depends on whether there is inheritance or +// not is the check in thread 2 on "3-ran" and "got it" flags marked **** +// +// +// volatile &c booleans: +// "got it" = FALSE +// "3-ran" = FALSE +// "3-ended" = FALSE +// "extras"[3] = FALSE +// +// thread 1. prio 5, self-suspend. +// +// thread 1a, prio 8, self-suspend. +// +// thread 2. prio 10, self-suspend. +// +// thread 2a, prio 12, self-suspend. +// +// thread 3. prio 15, runs, lock mutex, resume(2) +// +// thread 3a, prio 17, self-suspend. +// +// 2. runs, +// 2. resume(3a) +++OPTIONAL +// 2. resume(2a) +++OPTIONAL +// 2. resume(1a) +++OPTIONAL +// [1a lock-fail] thread 3->prio := 8 +// +// [3. runs maybe, does the looping thing] +// +// 2. sleep a while... +// +// [2a lock-fail] thread 3->prio := 12 +// +// [3. runs maybe, does the looping thing] +// +// [3a lock-fail] thread 3->prio unchanged +// +// [3. runs maybe, does the looping thing] +// +// 2. lock scheduler +// 2. set "go-flag" +// 2. resume(1) +// 2. resume(1a) +++OPTIONAL +// 2. resume(2a) +++OPTIONAL +// 2. resume(3a) +++OPTIONAL +// 2. unlock scheduler +// +// 1. runs, lock mutex - thread 3 has it locked +// +// 2. busy-waits a bit for thread 3 to come out of its delay() loop. +// This must be a *busy*wait so that 3 can only run via the +// inherited raised priority. +// +// [xa. all do the same: lock mutex, ] +// [xa. unlock mutex ] +// [xa. set a flag "extras"[x] to say we are done. ] +// [xa. exit ] +// +// +// +// INHERIT +// ------- +// +// thread 3->prio := 5 +// +// 3. runs, +// 3. set a flag to say "3-ran", +// 3. loop with a sleep(1) until "go-flag" is set. +// 3. check "got it" is false, +// 3. then unlock mutex, +// +// thread 3->prio := 15 +// +// 1. runs, set a flag to say "got it", +// 1. check "3-ended" flag is false +// 1. unlock mutex, +// 1. check "3-ended" flag is still false +// 1. exit. +// +// [1a locks, unlocks, exits] +// +// 2. runs, check "3-ran" and "got it" flags are TRUE **** +// 2. check "3-ended" flag is false +// 2. sleeps for a while so that... +// +// [2a locks, unlocks, exits] +// +// 3. runs, set "3-ended" flag, +// 3. check "3-ran" and "got it" flags +// 3. exit +// +// [3a locks, unlocks, exits] +// +// 2. awakens, checks all flags true, +// 2. check that all "extra" threads that we started have indeed run +// 2. end of test. +// +// +// +// +// NO-INHERIT +// ---------- +// thread 1 is waiting on the mutex +// +// [1a lock-fail] +// +// 2. runs, checks that "3-ran" and "got it" flags are FALSE **** +// 2. check "3-ended" flag is false +// 2. sleeps for a while so that... +// +// [2a. lock-fail] +// +// 3. runs, set a flag to say "3-ran", +// 3. check "got it" is false, +// 3. then unlock mutex, +// +// 1. runs, set a flag to say "got it", +// 1. check "3-ended" flag is false +// 1. unlock mutex, +// 1. check "3-ended" flag is still false +// 1. exit. +// +// [1a locks, unlocks, exits] +// [2a locks, unlocks, exits] +// +// 3. runs, set "3-ended" flag, +// 3. check "3-ran" and "got it" flags +// 3. exit +// +// [3a locks, unlocks, exits] +// +// 2. awakens, checks all flags true, +// 2. check that all "extra" threads that we started have indeed run +// 2. end of test. +// +// +// (the end) +// +// +// ------------------------------------------------------------------------ + +// EOF mutex3.cxx
--- a/packages/kernel/current/tests/stress_threads.c +++ b/packages/kernel/current/tests/stress_threads.c @@ -93,7 +93,6 @@ #define MAX_HANDLERS 4 #define N_LISTENERS 1 #define N_CLIENTS 1 -#define N_THREADS (N_MAIN+MAX_HANDLERS+N_LISTENERS+N_CLIENTS) #undef STACK_SIZE #undef STACK_SIZE_HANDLER @@ -107,26 +106,47 @@ #define MAX_HANDLERS 19 #define N_LISTENERS 4 #define N_CLIENTS 4 -#define N_THREADS (N_MAIN+MAX_HANDLERS+N_LISTENERS+N_CLIENTS) #endif /* Allocate priorities in this order. This ensures that handlers (which are the ones using the CPU) get enough CPU time to actually - complete their tasks. */ -//#define P_MAIN 0 // This is defined by libc -#define P_MAIN_PROGRAM 1 -#define P_BASE_HANDLER 2 -#define P_BASE_LISTENER (P_BASE_HANDLER+MAX_HANDLERS) -#define P_BASE_CLIENT (P_BASE_LISTENER+N_LISTENERS) -#define P_MAX (P_BASE_CLIENT+N_CLIENTS) + complete their tasks. + + The empty space ensures that if libc main() thread should happen to + be in the priority range of the handlers, no handlers are + accidently reduced so much in priority to get below + listeners/clients. */ + +#define P_MAIN_PROGRAM 1 +#define P_MAIN_PROGRAM_E (P_MAIN_PROGRAM+N_MAIN) + +#define P_BASE_HANDLER (P_MAIN_PROGRAM_E) +#define P_BASE_HANDLER_E (P_BASE_HANDLER+MAX_HANDLERS) +#define P_BASE_EMPTY (P_BASE_HANDLER_E) +#define P_BASE_EMPTY_E (P_BASE_EMPTY+2) -#if (CYGNUM_KERNEL_SCHED_PRIORITIES >= (P_MAX)) +#define P_BASE_LISTENER (P_BASE_EMPTY_E) +#define P_BASE_LISTENER_E (P_BASE_LISTENER+N_LISTENERS) + +#define P_BASE_CLIENT (P_BASE_LISTENER_E) +#define P_BASE_CLIENT_E (P_BASE_CLIENT+N_CLIENTS) + +#define P_MAX (P_BASE_CLIENT_E) + +/* Ensure there's room for what we request */ +#if (CYGNUM_KERNEL_SCHED_PRIORITIES >= P_MAX) /* if we use the bitmap scheduler we must make sure we don't use the same priority more than once, so we must store those already in use */ static volatile char priority_in_use[P_MAX]; +/* We may not get the priority we ask for (scheduler may decide to ignore + schedule hint). So keep a table of priorities actually assigned to + the threads. This information may come in handy for debugging - it's + not actively used by the code. */ +static volatile int priority_translation[P_MAX]; + /* now declare (and allocate space for) some kernel objects, like the threads we will use */ cyg_thread main_thread_s; @@ -200,7 +220,7 @@ struct s_statistics statistics; /* some function prototypes; those with the sc_ prefix are "statistics-collecting" versions of the cyg_ primitives */ -void sc_thread_create( +cyg_addrword_t sc_thread_create( cyg_addrword_t sched_info, /* scheduling info (eg pri) */ cyg_thread_entry_t *entry, /* entry point function */ cyg_addrword_t entry_data, /* entry data */ @@ -249,9 +269,10 @@ main(void) /* initialize main thread */ { - sc_thread_create(P_MAIN_PROGRAM, main_program, (cyg_addrword_t) 0, - "main_program", (void *) main_stack, STACK_SIZE, - &mainH, &main_thread_s); + priority_translation[P_MAIN_PROGRAM] = + sc_thread_create(P_MAIN_PROGRAM, main_program, (cyg_addrword_t) 0, + "main_program", (void *) main_stack, STACK_SIZE, + &mainH, &main_thread_s); priority_in_use[P_MAIN_PROGRAM]++; } @@ -263,20 +284,22 @@ main(void) for (i = 0; i < N_LISTENERS; ++i) { int prio = P_BASE_LISTENER + i; char* name = &thread_name[prio][0]; - sprintf(name, "listener-%02d/%02d", i, prio); - sc_thread_create(prio, listener_program, (cyg_addrword_t) i, - name, (void *) listener_stack[i], STACK_SIZE, - &listenerH[i], &listener_thread_s[i]); + sprintf(name, "listener-%02d", i); + priority_translation[prio] = + sc_thread_create(prio, listener_program, (cyg_addrword_t) i, + name, (void *) listener_stack[i], STACK_SIZE, + &listenerH[i], &listener_thread_s[i]); CYG_ASSERT(0 == priority_in_use[prio], "Priority already in use!"); priority_in_use[prio]++; } for (i = 0; i < N_CLIENTS; ++i) { int prio = P_BASE_CLIENT + i; char* name = &thread_name[prio][0]; - sprintf(name, "client-%02d/%02d", i, prio); - sc_thread_create(prio, client_program, (cyg_addrword_t) i, - name, (void *) client_stack[i], STACK_SIZE, - &(clientH[i]), &client_thread_s[i]); + sprintf(name, "client-%02d", i); + priority_translation[prio] = + sc_thread_create(prio, client_program, (cyg_addrword_t) i, + name, (void *) client_stack[i], STACK_SIZE, + &(clientH[i]), &client_thread_s[i]); CYG_ASSERT(0 == priority_in_use[prio], "Priority already in use!"); priority_in_use[prio]++; } @@ -477,11 +500,12 @@ void start_handler(void) name = &thread_name[prio][0]; sprintf(name, "handler-%02d/%02d", handler_slot, prio); - sc_thread_create(prio, handler_program, - (cyg_addrword_t) handler_slot, - name, (void *) handler_stack[handler_slot], - STACK_SIZE_HANDLER, &handlerH[handler_slot], - &handler_thread_s[handler_slot]); + priority_translation[prio] = + sc_thread_create(prio, handler_program, + (cyg_addrword_t) handler_slot, + name, (void *) handler_stack[handler_slot], + STACK_SIZE_HANDLER, &handlerH[handler_slot], + &handler_thread_s[handler_slot]); cyg_thread_resume(handlerH[handler_slot]); ++statistics.handler_invocation_histogram[handler_slot]; } @@ -644,7 +668,7 @@ void death_alarm_func(cyg_handle_t alarm } /* now I write the sc_ versions of the cyg_functions */ -void sc_thread_create( +cyg_addrword_t sc_thread_create( cyg_addrword_t sched_info, /* scheduling info (eg pri) */ cyg_thread_entry_t *entry, /* entry point function */ cyg_addrword_t entry_data, /* entry data */ @@ -656,11 +680,11 @@ void sc_thread_create( ) { ++statistics.thread_creations; + cyg_thread_create(sched_info, entry, entry_data, name, stack_base, stack_size, handle, thread); - CYG_ASSERT(cyg_thread_get_priority(*handle) == (cyg_priority_t) sched_info, - "Didn't get requested priority!"); + return cyg_thread_get_priority(*handle); }
