//======================================================================== // // dbg-threads-syscall.c // // Pseudo system calls for multi-threaded debug support // //======================================================================== //####ECOSGPLCOPYRIGHTBEGIN#### // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. // // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 or (at your option) any later version. // // eCos is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // // You should have received a copy of the GNU General Public License along // with eCos; if not, write to the Free Software Foundation, Inc., // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. // // As a special exception, if other files instantiate templates or use macros // or inline functions from this file, or you compile this file and link it // with other works to produce a work based on this file, this file does not // by itself cause the resulting work to be covered by the GNU General Public // License. However the source code for this file must still be made available // in accordance with section (3) of the GNU General Public License. // // This exception does not invalidate any other reasons why a work based on // this file might be covered by the GNU General Public License. // // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. // at http://sources.redhat.com/ecos/ecos-license/ // ------------------------------------------- //####ECOSGPLCOPYRIGHTEND#### //======================================================================== //#####DESCRIPTIONBEGIN#### // // Author(s): Red Hat, nickg // Contributors: Red Hat, nickg // Date: 1998-08-25 // Purpose: // Description: Pseudo system calls to bind system specific multithread // debug support with a ROM monitor, cygmon. We call it // Cygmon, but the feature lives in libstub. // Usage: // //####DESCRIPTIONEND#### // //======================================================================== #include #include #if !defined(CYGPKG_KERNEL) && defined(CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT) /* Only include this code if we do not have a kernel. Otherwise the kernel * supplies these functions for the app we are linked with. */ #include #include static dbg_syscall_func * dbg_syscall_ptr ; static union dbg_thread_syscall_parms tcall ; /* ----- INIT_THREADS_SYSCALL --------------------------------------- */ /* Some external bing and configuration logic knows how to setup the ststem calls. In the first implementation, we have used a vector in the secondary vector table. This functions allows us to isolate that sort of system specific detail. Similarly, we do not export the specific detail of a dbg_syscall_func. */ void init_threads_syscall(void * vector) { dbg_syscall_ptr = vector ; /* AH, the easy compatability of the void pointer*/ } /* init_threads_syscall */ /* All forms of failure return 0 */ /* Whether non support, incomplete initialization, unknown thread */ static __inline__ int dbg_thread_syscall( enum dbg_syscall_ids id) { dbg_syscall_func f ; /* double indirect via */ if (0 == dbg_syscall_ptr) return 0; /* dbg_syscall_ptr never init'd */ if (0 ==(f = *dbg_syscall_ptr)) return 0 ; /* vector not initialized */ return (*f)(id,&tcall); } /* ------- INIT_THREAD_SYSCALL ------------------------------------------- */ /* Received the address of the entry in the secondary interrupt vector table */ /* This table is the interchange between the O.S. and Cygmon/libstub */ /* This could get more complex so, I am doing it with a function rather than exposing the internals. */ void init_thread_syscall(void * vector) { dbg_syscall_ptr = vector ; } int dbg_thread_capabilities(struct dbg_capabilities * cbp) { #if 0 tcall.cap_parms.abilities = cbp ; return dbg_thread_syscall(dbg_capabilities_func) ; #else cbp->mask1 = has_thread_current | has_thread_registers | has_thread_reg_change | has_thread_list | has_thread_info ; return 1 ; #endif } int dbg_currthread(threadref * varparm) { tcall.currthread_parms.ref = varparm ; return dbg_thread_syscall(dbg_currthread_func) ; } int dbg_threadlist( int startflag, threadref * lastthreadid, threadref * next_thread ) { tcall.threadlist_parms.startflag = startflag ; tcall.threadlist_parms.lastid = lastthreadid ; tcall.threadlist_parms.nextthreadid = next_thread ; return dbg_thread_syscall(dbg_threadlist_func) ; } int dbg_threadinfo( threadref * threadid, struct cygmon_thread_debug_info * info) { tcall.info_parms.ref = threadid ; tcall.info_parms.info = info ; return dbg_thread_syscall(dbg_threadinfo_func) ; } int dbg_getthreadreg( threadref * osthreadid, int regcount, /* count of registers in the array */ void * regval) /* fillin this array */ { tcall.reg_parms.thread = osthreadid ; tcall.reg_parms.regcount = regcount ; tcall.reg_parms.registers = regval ; return dbg_thread_syscall(dbg_getthreadreg_func) ; } int dbg_setthreadreg( threadref * osthreadid, int regcount , /* number of registers */ void * regval) { tcall.reg_parms.thread = osthreadid ; tcall.reg_parms.regcount = regcount ; tcall.reg_parms.registers = regval ; return dbg_thread_syscall(dbg_setthreadreg_func) ; } /* dbg_setthreadreg */ int dbg_scheduler(threadref *thread_id, int lock, int mode) { tcall.scheduler_parms.thread = thread_id; tcall.scheduler_parms.lock = lock ; tcall.scheduler_parms.mode = mode ; return dbg_thread_syscall(dbg_scheduler_func) ; } #if (CYG_BYTEORDER == CYG_LSBFIRST) unsigned long swap32(unsigned long x) { unsigned long r = 0; r |= (x>>24)&0xFF; r |= ((x>>16)&0xFF) r |= ((x>>8)&0xFF) r |= ((x)&0xFF) return r; } #else #define swap32(x) ((unsigned long)(x)) #endif int dbg_currthread_id(void) { threadref ref; if( dbg_currthread( &ref ) ) return (cyg_uint16)swap32(((unsigned long *)ref)[1]); else return 0; } #endif