diff options
author | Stu Grossman <grossman@cygnus> | 1996-10-08 17:06:17 +0000 |
---|---|---|
committer | Stu Grossman <grossman@cygnus> | 1996-10-08 17:06:17 +0000 |
commit | 5d394f707245c12a8839461df83a06a0997c1698 (patch) | |
tree | 06c0637bdea1e07b710a7cee22575163e9a687fc | |
parent | 40d53fdf16a67f5b98c1f20b1e1c6fdccd74ca5d (diff) | |
download | ppe42-binutils-5d394f707245c12a8839461df83a06a0997c1698.tar.gz ppe42-binutils-5d394f707245c12a8839461df83a06a0997c1698.zip |
* Makefile.in: Add rule for hpux-thread.o (needs special header
files).
* (SUBDIRS): Remove mswin.
* Change procedure for creating init.c. Speeds things up quite a
bit.
* config.in configure configure.in: Check for select, poll.
* Check for OSF header files before including hpux-thread.o.
* Don't configure doc or testsuite when building under MSVC.
* findvar.c value.h (read_register_pid write_register_pid): Make
global. Needed for hppa-tdep.c.
* (supply_register): Don't set pid to inferior_pid when supplying
registers.
* hppa-tdep.c (saved_pc_after_call): frame_saved_pc ->
FRAME_SAVED_PC.
* (frame_saved_pc): Change name to hppa_frame_saved_pc.
* (hppa_pop_frame): Don't use a pid of 0 with target_write_pc.
Use write_pc instead, which uses the correct pid.
* (target_read_pc target_write_pc): Use read/write_register_pid
instead of read/write_register to preserve the pid passed in.
* inftarg.c (child_can_run): Add flag child_suppress_run to allow
hpux-threads.c to override this as a runnable target.
* config/pa/nm-hppah.h: Define target_new_objfile and
target_pid_to_str.
* config/pa/tm-hppa.h (FRAME_SAVED_PC): Use hppa_frame_saved_pc
instead of frame_saved_pc.
* config/m68k/tm-m68k.h: Define TARGET_M68K for Wingdb.
* config/m68k/tm-monitor.h: Use FRAME_CHAIN_VALID_ALTERNATE, since
we can't easily determine the start file bounds with ELF.
* config/mips/tm-mips.h: Define TARGET_MIPS for Wingdb.
* hpux-thread.c: New file for HPUX/OSF thread support.
* osf-share/{README AT386/cma_thread_io.h HP800/cma_thread_io.h
RIOS/cma_thread_io.h cma_attr.h cma_deb_core.h cma_debug_client.h
cma_errors.h cma_handle.h cma_init.h cma_list.h cma_mutex.h
cma_sched.h cma_semaphore_defs.h cma_sequence.h cma_stack.h
cma_stack_int.h cma_tcb_defs.h cma_util.h}: New files for OSF
thread support.
33 files changed, 4655 insertions, 36 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 40e65a6382..c275bafa17 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,42 @@ +Tue Oct 8 09:03:22 1996 Stu Grossman (grossman@critters.cygnus.com) + + * Makefile.in: Add rule for hpux-thread.o (needs special header + files). + * (SUBDIRS): Remove mswin. + * Change procedure for creating init.c. Speeds things up quite a + bit. + * config.in configure configure.in: Check for select, poll. + * Check for OSF header files before including hpux-thread.o. + * Don't configure doc or testsuite when building under MSVC. + * findvar.c value.h (read_register_pid write_register_pid): Make + global. Needed for hppa-tdep.c. + * (supply_register): Don't set pid to inferior_pid when supplying + registers. + * hppa-tdep.c (saved_pc_after_call): frame_saved_pc -> + FRAME_SAVED_PC. + * (frame_saved_pc): Change name to hppa_frame_saved_pc. + * (hppa_pop_frame): Don't use a pid of 0 with target_write_pc. + Use write_pc instead, which uses the correct pid. + * (target_read_pc target_write_pc): Use read/write_register_pid + instead of read/write_register to preserve the pid passed in. + * inftarg.c (child_can_run): Add flag child_suppress_run to allow + hpux-threads.c to override this as a runnable target. + * config/pa/nm-hppah.h: Define target_new_objfile and + target_pid_to_str. + * config/pa/tm-hppa.h (FRAME_SAVED_PC): Use hppa_frame_saved_pc + instead of frame_saved_pc. + * config/m68k/tm-m68k.h: Define TARGET_M68K for Wingdb. + * config/m68k/tm-monitor.h: Use FRAME_CHAIN_VALID_ALTERNATE, since + we can't easily determine the start file bounds with ELF. + * config/mips/tm-mips.h: Define TARGET_MIPS for Wingdb. + * hpux-thread.c: New file for HPUX/OSF thread support. + * osf-share/{README AT386/cma_thread_io.h HP800/cma_thread_io.h + RIOS/cma_thread_io.h cma_attr.h cma_deb_core.h cma_debug_client.h + cma_errors.h cma_handle.h cma_init.h cma_list.h cma_mutex.h + cma_sched.h cma_semaphore_defs.h cma_sequence.h cma_stack.h + cma_stack_int.h cma_tcb_defs.h cma_util.h}: New files for OSF + thread support. + Sun Oct 6 15:48:09 1996 Fred Fish <fnf@cygnus.com> * buildsym.c (finish_block): Change innerblock_anon_complaint to diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 344558c380..de5a5b8139 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -183,7 +183,8 @@ INTERNAL_CFLAGS = $(CFLAGS) $(GLOBAL_CFLAGS) $(PROFILE_CFLAGS) \ # Profiling options need to go here to work. # I think it's perfectly reasonable for a user to set -pg in CFLAGS # and have it work; that's why CFLAGS is here. -INTERNAL_LDFLAGS = $(CFLAGS) $(GLOBAL_CFLAGS) $(PROFILE_CFLAGS) $(LDFLAGS) @CONFIG_LDFLAGS@ +INTERNAL_LDFLAGS = $(CFLAGS) $(GLOBAL_CFLAGS) $(PROFILE_CFLAGS) $(LDFLAGS) @CONFIG_LDFLAGS@ @HLDFLAGS@ +HLDENV = @HLDENV@ # We are using our own version of REGEX now to be consistent across # machines. @@ -487,7 +488,7 @@ NTSOBS = standalone.o NTSSTART = kdb-start.o -SUBDIRS = doc testsuite nlm mswin +SUBDIRS = doc testsuite nlm # For now, shortcut the "configure GDB for fewer languages" stuff. YYFILES = c-exp.tab.c f-exp.tab.c m2-exp.tab.c @@ -585,9 +586,9 @@ init.c: $(OBS) $(TSOBS) @echo '#include "ansidecl.h"' >>init.c-tmp @echo 'extern void initialize_all_files PARAMS ((void));' >>init.c-tmp @echo 'void initialize_all_files PARAMS ((void)) {' >>init.c-tmp - @for i in $(OBS) $(TSOBS); do \ - filename=`echo $$i | sed \ - -e '/^Onindy.o/d' \ + @echo $(OBS) $(TSOBS) | \ + tr ' ' '\012' | \ + sed -e '/^Onindy.o/d' \ -e '/^nindy.o/d' \ -e '/ttyflush.o/d' \ -e '/xdr_ld.o/d' \ @@ -599,13 +600,10 @@ init.c: $(OBS) $(TSOBS) -e '/version.o/d' \ -e '/^[a-z0-9A-Z_]*_[SU].o/d' \ -e '/[a-z0-9A-Z_]*-exp.tab.o/d' \ - -e 's/\.o/.c/'` ; \ - case $$filename in \ - "") ;; \ - *) sed <$(srcdir)/$$filename >>init.c-tmp -n \ - -e '/^_initialize_[a-z_0-9A-Z]* *(/s/^\([a-z_0-9A-Z]*\).*/ {extern void \1 PARAMS ((void)); \1 ();}/p' ; ;; \ - esac ; \ - done + -e 's/\.o/.c/' \ + -e 's|\([^ ][^ ]*\)|$(srcdir)/\1|g' | \ + xargs grep -h -s '^_initialize_[a-z_0-9A-Z]* *(' | \ + sed -e 's/^\([a-z_0-9A-Z]*\).*/ {extern void \1 PARAMS ((void)); \1 ();}/p' >>init.c-tmp @echo '}' >>init.c-tmp @mv init.c-tmp init.c @@ -614,7 +612,7 @@ init.c: $(OBS) $(TSOBS) # Removing the old gdb first works better if it is running, at least on SunOS. gdb: $(OBS) $(TSOBS) $(ADD_DEPS) $(CDEPS) init.o rm -f gdb - $(CC_LD) $(INTERNAL_LDFLAGS) -o gdb \ + $(HLDENV) $(CC_LD) $(INTERNAL_LDFLAGS) -o gdb \ init.o $(OBS) $(TSOBS) $(ADD_FILES) $(CLIBS) $(LOADLIBES) nlm: force @@ -622,9 +620,6 @@ nlm: force libgdb: libgdb-files $(LIBGDB_OBS) -mswin/libwingdb.a: force - rootme=`pwd`; export rootme; $(MAKE) $(FLAGS_TO_PASS) DO=all DODIRS=mswin subdir_do - # libproc is not listed here because all-libproc is a dependency of all-gui, # not all-gdb, and thus might be built after us. LIBGDBDEPS=$(COMMON_OBS) $(LIBGDB_OBS) $(TSOBS) $(ADD_DEPS) $(CDEPS) init.o @@ -1326,6 +1321,10 @@ somread.o: somread.c $(bfd_h) buildsym.h complaints.h $(defs_h) \ somsolib.o: somsolib.c $(defs_h) +hpux-thread.o: hpux-thread.c $(defs_h) gdbthread.h target.h inferior.h + $(CC) -c $(INTERNAL_CFLAGS) -I$(srcdir)/osf-share \ + -I$(srcdir)/osf-share/HP800 -I/usr/include/dce $(srcdir)/hpux-thread.c + hpread.o: hpread.c $(bfd_h) buildsym.h complaints.h $(defs_h) \ gdb-stabs.h objfiles.h symfile.h $(symtab_h) gdb_string.h diff --git a/gdb/config.in b/gdb/config.in index a3b3e51f17..a719fb0ec8 100644 --- a/gdb/config.in +++ b/gdb/config.in @@ -109,3 +109,12 @@ /* Define if you have the <unistd.h> header file. */ #undef HAVE_UNISTD_H + +/* Define if you have the select function. */ +#undef HAVE_SELECT + +/* Define if you have the poll function. */ +#undef HAVE_POLL + +/* Define if you have HPUX threads */ +#undef HAVE_HPUX_THREAD_SUPPORT diff --git a/gdb/config/m68k/tm-m68k.h b/gdb/config/m68k/tm-m68k.h index 6305f592b3..e21fd288f8 100644 --- a/gdb/config/m68k/tm-m68k.h +++ b/gdb/config/m68k/tm-m68k.h @@ -387,3 +387,5 @@ extern void m68k_pop_frame PARAMS ((void)); /* Offset from SP to first arg on stack at first instruction of a function */ #define SP_ARG0 (1 * 4) + +#define TARGET_M68K diff --git a/gdb/config/mips/tm-mips.h b/gdb/config/mips/tm-mips.h index 841b7fee50..d96dd0bfaa 100644 --- a/gdb/config/mips/tm-mips.h +++ b/gdb/config/mips/tm-mips.h @@ -543,4 +543,6 @@ extern void fixup_sigtramp PARAMS ((void)); /* Defined in mips-tdep.c and used in remote-mips.c */ extern char *mips_read_processor_type PARAMS ((void)); +#define TARGET_MIPS + #endif /* TM_MIPS_H */ diff --git a/gdb/config/pa/nm-hppah.h b/gdb/config/pa/nm-hppah.h index d40e5f8bbf..1584c9b5bf 100644 --- a/gdb/config/pa/nm-hppah.h +++ b/gdb/config/pa/nm-hppah.h @@ -75,3 +75,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ target process... Which really pisses off GDB.) */ #define ATTACH_DETACH + +#ifdef HAVE_HPUX_THREAD_SUPPORT + +#ifdef __STDC__ +struct objfile; +#endif + +void hpux_thread_new_objfile PARAMS ((struct objfile *objfile)); +#define target_new_objfile(OBJFILE) hpux_thread_new_objfile (OBJFILE) + +extern char *hpux_pid_to_str PARAMS ((int pid)); +#define target_pid_to_str(PID) hpux_pid_to_str (PID) + +#endif /* HAVE_HPUX_THREAD_SUPPORT */ diff --git a/gdb/configure b/gdb/configure index b39ee60594..9a6742be0c 100755 --- a/gdb/configure +++ b/gdb/configure @@ -1461,7 +1461,7 @@ EOF fi -for ac_func in setpgid sbrk +for ac_func in setpgid sbrk select poll do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then @@ -2044,6 +2044,21 @@ EOF else echo "$ac_t""no" 1>&6 fi + case ${host_os} in + hpux*) + echo $ac_n "checking for HPUX/OSF thread support""... $ac_c" 1>&6 + if test -f /usr/include/dce/cma_config.h ; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_HPUX_THREAD_SUPPORT 1 +EOF + + THREAD_DB_OBS=hpux-thread.o + else + echo "$ac_t""no" 1>&6 + fi + ;; + esac fi @@ -2422,12 +2437,12 @@ if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2426 "configure" +#line 2441 "configure" #include "confdefs.h" #include <tclInt.h> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2431: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2446: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -2554,12 +2569,12 @@ if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2558 "configure" +#line 2573 "configure" #include "confdefs.h" #include <tk.h> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2563: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2578: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -2763,7 +2778,7 @@ i[3456]86-*-isc*) gdb_host=i386v32 ;; i[3456]86-*-os9k) gdb_host=i386os9k ;; i[3456]86-*-cygwin32) gdb_host=cygwin32 ;; i[3456]86-*-windows) gdb_host=windows - configdirs="${configdirs} mswin" ;; + configdirs=mswin ;; m680[01]0-sun-sunos3*) gdb_host=sun2os3 ;; m680[01]0-sun-sunos4*) gdb_host=sun2os4 ;; m68030-sony-*) gdb_host=news1000 ;; diff --git a/gdb/configure.in b/gdb/configure.in index 4b794f4d38..9f0abde5e1 100644 --- a/gdb/configure.in +++ b/gdb/configure.in @@ -45,7 +45,7 @@ AC_HEADER_STAT AC_C_CONST -AC_CHECK_FUNCS(setpgid sbrk) +AC_CHECK_FUNCS(setpgid sbrk select poll) # If we are configured native on Linux, work around problems with sys/procfs.h if test "${target}" = "${host}"; then @@ -163,6 +163,18 @@ if test ${build} = ${host} -a ${host} = ${target} ; then else AC_MSG_RESULT(no) fi + case ${host_os} in + hpux*) + AC_MSG_CHECKING(for HPUX/OSF thread support) + if test -f /usr/include/dce/cma_config.h ; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_HPUX_THREAD_SUPPORT) + THREAD_DB_OBS=hpux-thread.o + else + AC_MSG_RESULT(no) + fi + ;; + esac AC_SUBST(THREAD_DB_OBS) AC_SUBST(CONFIG_LDFLAGS) fi @@ -414,7 +426,7 @@ i[3456]86-*-isc*) gdb_host=i386v32 ;; i[3456]86-*-os9k) gdb_host=i386os9k ;; i[3456]86-*-cygwin32) gdb_host=cygwin32 ;; i[3456]86-*-windows) gdb_host=windows - configdirs="${configdirs} mswin" ;; + configdirs=mswin ;; m680[01]0-sun-sunos3*) gdb_host=sun2os3 ;; m680[01]0-sun-sunos4*) gdb_host=sun2os4 ;; m68030-sony-*) gdb_host=news1000 ;; diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c index 3c3f0583cc..05463b4f7d 100644 --- a/gdb/hppa-tdep.c +++ b/gdb/hppa-tdep.c @@ -812,13 +812,13 @@ saved_pc_after_call (frame) the stub will return to out of the stack. */ u = find_unwind_entry (pc); if (u && u->stub_type != 0) - return frame_saved_pc (frame); + return FRAME_SAVED_PC (frame); else return pc; } CORE_ADDR -frame_saved_pc (frame) +hppa_frame_saved_pc (frame) struct frame_info *frame; { CORE_ADDR pc = get_frame_pc (frame); @@ -1394,7 +1394,7 @@ hppa_pop_frame () else { npc = read_register (RP_REGNUM); - target_write_pc (npc, 0); + write_pc (npc); } write_register (FP_REGNUM, read_memory_integer (fp, 4)); @@ -1749,12 +1749,15 @@ CORE_ADDR target_read_pc (pid) int pid; { - int flags = read_register (FLAGS_REGNUM); + int flags = read_register_pid (FLAGS_REGNUM, pid); - if (flags & 2) { - return read_register (31) & ~0x3; - } - return read_register (PC_REGNUM) & ~0x3; + /* The following test does not belong here. It is OS-specific, and belongs + in native code. */ + /* Test SS_INSYSCALL */ + if (flags & 2) + return read_register_pid (31, pid) & ~0x3; + + return read_register_pid (PC_REGNUM, pid) & ~0x3; } /* Write out the PC. If currently in a syscall, then also write the new @@ -1765,15 +1768,18 @@ target_write_pc (v, pid) CORE_ADDR v; int pid; { - int flags = read_register (FLAGS_REGNUM); + int flags = read_register_pid (FLAGS_REGNUM, pid); + /* The following test does not belong here. It is OS-specific, and belongs + in native code. */ /* If in a syscall, then set %r31. Also make sure to get the privilege bits set correctly. */ + /* Test SS_INSYSCALL */ if (flags & 2) - write_register (31, (long) (v | 0x3)); + write_register_pid (31, v | 0x3, pid); - write_register (PC_REGNUM, (long) v); - write_register (NPC_REGNUM, (long) v + 4); + write_register_pid (PC_REGNUM, v, pid); + write_register_pid (NPC_REGNUM, v + 4, pid); } /* return the alignment of a type in bytes. Structures have the maximum diff --git a/gdb/hpux-thread.c b/gdb/hpux-thread.c new file mode 100644 index 0000000000..b8c227ab69 --- /dev/null +++ b/gdb/hpux-thread.c @@ -0,0 +1,638 @@ +/* Low level interface for debugging HPUX/DCE threads for GDB, the GNU debugger. + Copyright 1996 Free Software Foundation, Inc. + +This file is part of GDB. + +This program 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 of the License, or +(at your option) any later version. + +This program 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 this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* This module implements a sort of half target that sits between the + machine-independent parts of GDB and the ptrace interface (infptrace.c) to + provide access to the HPUX user-mode thread implementation. + + HPUX threads are true user-mode threads, which are invoked via the cma_* + and pthread_* (DCE and Posix respectivly) interfaces. These are mostly + implemented in user-space, with all thread context kept in various + structures that live in the user's heap. For the most part, the kernel has + no knowlege of these threads. + + */ + +#include "defs.h" + +#define _CMA_NOWRAPPERS_ + +#include <cma_tcb_defs.h> +#include <cma_deb_core.h> +#include "gdbthread.h" +#include "target.h" +#include "inferior.h" +#include <fcntl.h> +#include <unistd.h> +#include <sys/stat.h> +#include "gdbcore.h" + +extern struct target_ops hpux_thread_ops; /* Forward declaration */ + +extern int child_suppress_run; +extern struct target_ops child_ops; /* target vector for inftarg.c */ + +struct string_map +{ + int num; + char *str; +}; + +static int hpux_thread_active = 0; + +static int main_pid; /* Real process ID */ + +static CORE_ADDR P_cma__g_known_threads; +static CORE_ADDR P_cma__g_current_thread; + +static struct cleanup * save_inferior_pid PARAMS ((void)); +static void restore_inferior_pid PARAMS ((int pid)); +static void hpux_thread_resume PARAMS ((int pid, int step, + enum target_signal signo)); + +/* + +LOCAL FUNCTION + + save_inferior_pid - Save inferior_pid on the cleanup list + restore_inferior_pid - Restore inferior_pid from the cleanup list + +SYNOPSIS + + struct cleanup *save_inferior_pid () + void restore_inferior_pid (int pid) + +DESCRIPTION + + These two functions act in unison to restore inferior_pid in + case of an error. + +NOTES + + inferior_pid is a global variable that needs to be changed by many of + these routines before calling functions in procfs.c. In order to + guarantee that inferior_pid gets restored (in case of errors), you + need to call save_inferior_pid before changing it. At the end of the + function, you should invoke do_cleanups to restore it. + + */ + + +static struct cleanup * +save_inferior_pid () +{ + return make_cleanup (restore_inferior_pid, inferior_pid); +} + +static void +restore_inferior_pid (pid) + int pid; +{ + inferior_pid = pid; +} + +static int find_active_thread PARAMS ((void)); + +static int cached_thread; +static int cached_active_thread; +static cma__t_int_tcb cached_tcb; + +static int +find_active_thread () +{ + static cma__t_int_tcb tcb; + CORE_ADDR tcb_ptr; + + if (cached_active_thread != 0) + return cached_active_thread; + + read_memory ((CORE_ADDR)P_cma__g_current_thread, + (char *)&tcb_ptr, + sizeof tcb_ptr); + + read_memory (tcb_ptr, (char *)&tcb, sizeof tcb); + + return (cma_thread_get_unique (&tcb.prolog.client_thread) << 16) | main_pid; +} + +static cma__t_int_tcb * find_tcb PARAMS ((int thread)); + +static cma__t_int_tcb * +find_tcb (thread) + int thread; +{ + cma__t_known_object queue_header; + cma__t_queue *queue_ptr; + + if (thread == cached_thread) + return &cached_tcb; + + read_memory ((CORE_ADDR)P_cma__g_known_threads, + (char *)&queue_header, + sizeof queue_header); + + for (queue_ptr = queue_header.queue.flink; + queue_ptr != (cma__t_queue *)P_cma__g_known_threads; + queue_ptr = cached_tcb.threads.flink) + { + cma__t_int_tcb *tcb_ptr; + + tcb_ptr = cma__base (queue_ptr, threads, cma__t_int_tcb); + + read_memory ((CORE_ADDR)tcb_ptr, (char *)&cached_tcb, sizeof cached_tcb); + + if (cached_tcb.header.type == cma__c_obj_tcb) + if (cma_thread_get_unique (&cached_tcb.prolog.client_thread) == thread >> 16) + { + cached_thread = thread; + return &cached_tcb; + } + } + + error ("Can't find TCB %d,%d", thread >> 16, thread & 0xffff); + return NULL; +} + +/* Most target vector functions from here on actually just pass through to + inftarg.c, as they don't need to do anything specific for threads. */ + +/* ARGSUSED */ +static void +hpux_thread_open (arg, from_tty) + char *arg; + int from_tty; +{ + child_ops.to_open (arg, from_tty); +} + +/* Attach to process PID, then initialize for debugging it + and wait for the trace-trap that results from attaching. */ + +static void +hpux_thread_attach (args, from_tty) + char *args; + int from_tty; +{ + child_ops.to_attach (args, from_tty); + + /* XXX - might want to iterate over all the threads and register them. */ +} + +/* Take a program previously attached to and detaches it. + The program resumes execution and will no longer stop + on signals, etc. We'd better not have left any breakpoints + in the program or it'll die when it hits one. For this + to work, it may be necessary for the process to have been + previously attached. It *might* work if the program was + started via the normal ptrace (PTRACE_TRACEME). */ + +static void +hpux_thread_detach (args, from_tty) + char *args; + int from_tty; +{ + child_ops.to_detach (args, from_tty); +} + +/* Resume execution of process PID. If STEP is nozero, then + just single step it. If SIGNAL is nonzero, restart it with that + signal activated. We may have to convert pid from a thread-id to an LWP id + for procfs. */ + +static void +hpux_thread_resume (pid, step, signo) + int pid; + int step; + enum target_signal signo; +{ + struct cleanup *old_chain; + + old_chain = save_inferior_pid (); + + pid = inferior_pid = main_pid; + +#if 0 + if (pid != -1) + { + pid = thread_to_lwp (pid, -2); + if (pid == -2) /* Inactive thread */ + error ("This version of Solaris can't start inactive threads."); + } +#endif + + child_ops.to_resume (pid, step, signo); + + cached_thread = 0; + cached_active_thread = 0; + + do_cleanups (old_chain); +} + +/* Wait for any threads to stop. We may have to convert PID from a thread id + to a LWP id, and vice versa on the way out. */ + +static int +hpux_thread_wait (pid, ourstatus) + int pid; + struct target_waitstatus *ourstatus; +{ + int rtnval; + struct cleanup *old_chain; + + old_chain = save_inferior_pid (); + + inferior_pid = main_pid; + + if (pid != -1) + pid = main_pid; + + rtnval = child_ops.to_wait (pid, ourstatus); + + rtnval = find_active_thread (); + + do_cleanups (old_chain); + + return rtnval; +} + +static char regmap[NUM_REGS] = +{ + -2, -1, -1, 0, 4, 8, 12, 16, 20, 24, /* flags, r1 -> r9 */ + 28, 32, 36, 40, 44, 48, 52, 56, 60, -1, /* r10 -> r19 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* r20 -> r29 */ + + /* r30, r31, sar, pcoqh, pcsqh, pcoqt, pcsqt, eiem, iir, isr */ + -2, -1, -1, -2, -1, -1, -1, -1, -1, -1, + + /* ior, ipsw, goto, sr4, sr0, sr1, sr2, sr3, sr5, sr6 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + + /* sr7, cr0, cr8, cr9, ccr, cr12, cr13, cr24, cr25, cr26 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + + -1, -1, -1, -1, /* mpsfu_high, mpsfu_low, mpsfu_ovflo, pad */ + 144, -1, -1, -1, -1, -1, -1, -1, /* fpsr, fpe1 -> fpe7 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* fr4 -> fr7 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* fr8 -> fr11 */ + 136, -1, 128, -1, 120, -1, 112, -1, /* fr12 -> fr15 */ + 104, -1, 96, -1, 88, -1, 80, -1, /* fr16 -> fr19 */ + 72, -1, 64, -1, -1, -1, -1, -1, /* fr20 -> fr23 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* fr24 -> fr27 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* fr28 -> fr31 */ +}; + +static void +hpux_thread_fetch_registers (regno) + int regno; +{ + cma__t_int_tcb tcb, *tcb_ptr; + struct cleanup *old_chain; + int i; + int first_regno, last_regno; + + tcb_ptr = find_tcb (inferior_pid); + + old_chain = save_inferior_pid (); + + inferior_pid = main_pid; + + if (tcb_ptr->state == cma__c_state_running) + { + child_ops.to_fetch_registers (regno); + + do_cleanups (old_chain); + + return; + } + + if (regno == -1) + { + first_regno = 0; + last_regno = NUM_REGS - 1; + } + else + { + first_regno = regno; + last_regno = regno; + } + + for (regno = first_regno; regno <= last_regno; regno++) + { + if (regmap[regno] == -1) + child_ops.to_fetch_registers (regno); + else + { + unsigned char buf[MAX_REGISTER_RAW_SIZE]; + CORE_ADDR sp; + + sp = (CORE_ADDR)tcb_ptr->static_ctx.sp - 160; + + if (regno == FLAGS_REGNUM) + /* Flags must be 0 to avoid bogus value for SS_INSYSCALL */ + memset (buf, '\000', REGISTER_RAW_SIZE (regno)); + else if (regno == SP_REGNUM) + store_address (buf, sizeof sp, sp); + else if (regno == PC_REGNUM) + read_memory (sp - 20, buf, REGISTER_RAW_SIZE (regno)); + else + read_memory (sp + regmap[regno], buf, REGISTER_RAW_SIZE (regno)); + + supply_register (regno, buf); + } + } + + do_cleanups (old_chain); +} + +static void +hpux_thread_store_registers (regno) + int regno; +{ + cma__t_int_tcb tcb, *tcb_ptr; + struct cleanup *old_chain; + int i; + int first_regno, last_regno; + + tcb_ptr = find_tcb (inferior_pid); + + old_chain = save_inferior_pid (); + + inferior_pid = main_pid; + + if (tcb_ptr->state == cma__c_state_running) + { + child_ops.to_store_registers (regno); + + do_cleanups (old_chain); + + return; + } + + if (regno == -1) + { + first_regno = 0; + last_regno = NUM_REGS - 1; + } + else + { + first_regno = regno; + last_regno = regno; + } + + for (regno = first_regno; regno <= last_regno; regno++) + { + if (regmap[regno] == -1) + child_ops.to_store_registers (regno); + else + { + unsigned char buf[MAX_REGISTER_RAW_SIZE]; + CORE_ADDR sp; + + sp = (CORE_ADDR)tcb_ptr->static_ctx.sp - 160; + + if (regno == FLAGS_REGNUM) + child_ops.to_store_registers (regno); /* Let lower layer handle this... */ + else if (regno == SP_REGNUM) + { + write_memory ((CORE_ADDR)&tcb_ptr->static_ctx.sp, + registers + REGISTER_BYTE (regno), + REGISTER_RAW_SIZE (regno)); + tcb_ptr->static_ctx.sp = (cma__t_hppa_regs *) + (extract_address (registers + REGISTER_BYTE (regno), REGISTER_RAW_SIZE (regno)) + 160); + } + else if (regno == PC_REGNUM) + write_memory (sp - 20, + registers + REGISTER_BYTE (regno), + REGISTER_RAW_SIZE (regno)); + else + write_memory (sp + regmap[regno], + registers + REGISTER_BYTE (regno), + REGISTER_RAW_SIZE (regno)); + } + } + + do_cleanups (old_chain); +} + +/* Get ready to modify the registers array. On machines which store + individual registers, this doesn't need to do anything. On machines + which store all the registers in one fell swoop, this makes sure + that registers contains all the registers from the program being + debugged. */ + +static void +hpux_thread_prepare_to_store () +{ + child_ops.to_prepare_to_store (); +} + +static int +hpux_thread_xfer_memory (memaddr, myaddr, len, dowrite, target) + CORE_ADDR memaddr; + char *myaddr; + int len; + int dowrite; + struct target_ops *target; /* ignored */ +{ + int retval; + struct cleanup *old_chain; + + old_chain = save_inferior_pid (); + + inferior_pid = main_pid; + + retval = child_ops.to_xfer_memory (memaddr, myaddr, len, dowrite, target); + + do_cleanups (old_chain); + + return retval; +} + +/* Print status information about what we're accessing. */ + +static void +hpux_thread_files_info (ignore) + struct target_ops *ignore; +{ + child_ops.to_files_info (ignore); +} + +static void +hpux_thread_kill_inferior () +{ + child_ops.to_kill (); +} + +static void +hpux_thread_notice_signals (pid) + int pid; +{ + child_ops.to_notice_signals (pid); +} + +/* Fork an inferior process, and start debugging it with /proc. */ + +static void +hpux_thread_create_inferior (exec_file, allargs, env) + char *exec_file; + char *allargs; + char **env; +{ + child_ops.to_create_inferior (exec_file, allargs, env); + + if (hpux_thread_active) + { + main_pid = inferior_pid; + + push_target (&hpux_thread_ops); + + inferior_pid = find_active_thread (); + + add_thread (inferior_pid); + } +} + +/* This routine is called whenever a new symbol table is read in, or when all + symbol tables are removed. libthread_db can only be initialized when it + finds the right variables in libthread.so. Since it's a shared library, + those variables don't show up until the library gets mapped and the symbol + table is read in. */ + +void +hpux_thread_new_objfile (objfile) + struct objfile *objfile; +{ + struct minimal_symbol *ms; + + if (!objfile) + { + hpux_thread_active = 0; + + return; + } + + ms = lookup_minimal_symbol ("cma__g_known_threads", NULL, objfile); + + if (!ms) + return; + + P_cma__g_known_threads = SYMBOL_VALUE_ADDRESS (ms); + + ms = lookup_minimal_symbol ("cma__g_current_thread", NULL, objfile); + + if (!ms) + return; + + P_cma__g_current_thread = SYMBOL_VALUE_ADDRESS (ms); + + hpux_thread_active = 1; +} + +/* Clean up after the inferior dies. */ + +static void +hpux_thread_mourn_inferior () +{ + child_ops.to_mourn_inferior (); +} + +/* Mark our target-struct as eligible for stray "run" and "attach" commands. */ + +static int +hpux_thread_can_run () +{ + return child_suppress_run; +} + +static int +hpux_thread_alive (pid) + int pid; +{ + return 1; +} + +static void +hpux_thread_stop () +{ + child_ops.to_stop (); +} + +/* Convert a pid to printable form. */ + +char * +hpux_pid_to_str (pid) + int pid; +{ + static char buf[100]; + + sprintf (buf, "Thread %d", pid >> 16); + + return buf; +} + +struct target_ops hpux_thread_ops = { + "hpux-threads", /* to_shortname */ + "HPUX threads and pthread.", /* to_longname */ + "HPUX threads and pthread support.", /* to_doc */ + hpux_thread_open, /* to_open */ + 0, /* to_close */ + hpux_thread_attach, /* to_attach */ + hpux_thread_detach, /* to_detach */ + hpux_thread_resume, /* to_resume */ + hpux_thread_wait, /* to_wait */ + hpux_thread_fetch_registers, /* to_fetch_registers */ + hpux_thread_store_registers, /* to_store_registers */ + hpux_thread_prepare_to_store, /* to_prepare_to_store */ + hpux_thread_xfer_memory, /* to_xfer_memory */ + hpux_thread_files_info, /* to_files_info */ + memory_insert_breakpoint, /* to_insert_breakpoint */ + memory_remove_breakpoint, /* to_remove_breakpoint */ + terminal_init_inferior, /* to_terminal_init */ + terminal_inferior, /* to_terminal_inferior */ + terminal_ours_for_output, /* to_terminal_ours_for_output */ + terminal_ours, /* to_terminal_ours */ + child_terminal_info, /* to_terminal_info */ + hpux_thread_kill_inferior, /* to_kill */ + 0, /* to_load */ + 0, /* to_lookup_symbol */ + hpux_thread_create_inferior, /* to_create_inferior */ + hpux_thread_mourn_inferior, /* to_mourn_inferior */ + hpux_thread_can_run, /* to_can_run */ + hpux_thread_notice_signals, /* to_notice_signals */ + hpux_thread_alive, /* to_thread_alive */ + hpux_thread_stop, /* to_stop */ + process_stratum, /* to_stratum */ + 0, /* to_next */ + 1, /* to_has_all_memory */ + 1, /* to_has_memory */ + 1, /* to_has_stack */ + 1, /* to_has_registers */ + 1, /* to_has_execution */ + 0, /* sections */ + 0, /* sections_end */ + OPS_MAGIC /* to_magic */ +}; + +void +_initialize_hpux_thread () +{ + add_target (&hpux_thread_ops); + + child_suppress_run = 1; +} diff --git a/gdb/osf-share/.Sanitize b/gdb/osf-share/.Sanitize new file mode 100644 index 0000000000..1a2c4265ab --- /dev/null +++ b/gdb/osf-share/.Sanitize @@ -0,0 +1,61 @@ +# .Sanitize for devo/gdb/osf-share. + +# Each directory to survive its way into a release will need a file +# like this one called "./.Sanitize". All keyword lines must exist, +# and must exist in the order specified by this file. Each directory +# in the tree will be processed, top down, in the following order. + +# Hash started lines like this one are comments and will be deleted +# before anything else is done. Blank lines will also be squashed +# out. + +# The lines between the "Do-first:" line and the "Things-to-keep:" +# line are executed as a /bin/sh shell script before anything else is +# done in this directory. + +Do-first: + +# All files listed between the "Things-to-keep:" line and the +# "Files-to-sed:" line will be kept. All other files will be removed. +# Directories listed in this section will have their own Sanitize +# called. Directories not listed will be removed in their entirety +# with rm -rf. + +Things-to-keep: + +AT386 +HP800 +RIOS +cma_attr.h +cma_deb_core.h +cma_debug_client.h +cma_errors.h +cma_handle.h +cma_init.h +cma_list.h +cma_mutex.h +cma_sched.h +cma_semaphore_defs.h +cma_sequence.h +cma_stack.h +cma_stack_int.h +cma_tcb_defs.h +cma_util.h + +# Things which are explicitly *not* kept, for now. + +Things-to-lose: + +Do-last: + +# Don't try to clean directories here, as the 'mv' command will fail. +# Also, grep fails on NFS mounted directories. + +for i in * ; do + if test ! -d $i && (grep sanitize $i > /dev/null) ; then + echo '***' Some mentions of Sanitize are still left in $i! 1>&2 + fi +done + +# +# End of file. diff --git a/gdb/osf-share/AT386/.Sanitize b/gdb/osf-share/AT386/.Sanitize new file mode 100644 index 0000000000..2ef8e54322 --- /dev/null +++ b/gdb/osf-share/AT386/.Sanitize @@ -0,0 +1,44 @@ +# .Sanitize for devo/gdb/osf-share/AT386. + +# Each directory to survive its way into a release will need a file +# like this one called "./.Sanitize". All keyword lines must exist, +# and must exist in the order specified by this file. Each directory +# in the tree will be processed, top down, in the following order. + +# Hash started lines like this one are comments and will be deleted +# before anything else is done. Blank lines will also be squashed +# out. + +# The lines between the "Do-first:" line and the "Things-to-keep:" +# line are executed as a /bin/sh shell script before anything else is +# done in this directory. + +Do-first: + +# All files listed between the "Things-to-keep:" line and the +# "Files-to-sed:" line will be kept. All other files will be removed. +# Directories listed in this section will have their own Sanitize +# called. Directories not listed will be removed in their entirety +# with rm -rf. + +Things-to-keep: + +cma_thread_io.h + +# Things which are explicitly *not* kept, for now. + +Things-to-lose: + +Do-last: + +# Don't try to clean directories here, as the 'mv' command will fail. +# Also, grep fails on NFS mounted directories. + +for i in * ; do + if test ! -d $i && (grep sanitize $i > /dev/null) ; then + echo '***' Some mentions of Sanitize are still left in $i! 1>&2 + fi +done + +# +# End of file. diff --git a/gdb/osf-share/AT386/cma_thread_io.h b/gdb/osf-share/AT386/cma_thread_io.h new file mode 100644 index 0000000000..a90dba1758 --- /dev/null +++ b/gdb/osf-share/AT386/cma_thread_io.h @@ -0,0 +1,457 @@ +/* + * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC. + * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY + * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION + * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems + * To anyone who acknowledges that this file is provided "AS IS" without + * any express or implied warranty: permission to use, copy, modify, and + * distribute this file for any purpose is hereby granted without fee, + * provided that the above copyright notices and this notice appears in + * all source code copies, and that none of the names listed above be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. None of these organizations + * makes any representations about the suitability of this software for + * any purpose. + */ +/* + * Header file for thread synchrounous I/O + */ + +#ifndef CMA_THREAD_IO +#define CMA_THREAD_IO + +/* + * INCLUDE FILES + */ + +#include <cma_config.h> +#include <sys/file.h> +#include <cma.h> +#include <sys/types.h> +#include <sys/time.h> +#include <cma_init.h> +#include <cma_errors.h> + +/* + * CONSTANTS + */ + +/* + * Define symbols which indicate whether to compile code for obsolete + * "non-blocking mode" flags: FNDELAY and FNBLOCK. If the obsolete + * symbols are defined, and if their replacement symbols are defined + * and are different or if they are undefined, then define a symbol + * that says to compile the code in; otherwise no code will be compiled + * for these obsolete symbols. + */ +#ifdef FNDELAY +# ifdef O_NDELAY +# if O_NDELAY != FNDELAY +# define _CMA_FNDELAY_ +# endif +# else +# define _CMA_FNDELAY_ +# endif +#endif + +#ifdef FNBLOCK +# ifdef O_NONBLOCK +# if O_NONBLOCK != FNBLOCK +# define _CMA_FNBLOCK_ +# endif +# else +# define _CMA_FNBLOCK_ +# endif +#endif + + +extern cma_t_boolean cma_is_open(int); +/* + * Maximum number of files (ie, max_fd+1) + */ +#define cma__c_mx_file FD_SETSIZE + +/* + * Number of bits per file descriptor bit mask (ie number of bytes * bits/byte) + */ +#define cma__c_nbpm NFDBITS + +/* + * TYPE DEFINITIONS + */ + +typedef enum CMA__T_IO_TYPE { + cma__c_io_read = 0, + cma__c_io_write = 1, + cma__c_io_except = 2 + } cma__t_io_type; +#define cma__c_max_io_type 2 + +/* + * From our local <sys/types.h>: + * + * typedef long fd_mask; + * + * typedef struct fd_set { + * fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)]; + * } fd_set; + * + */ +typedef fd_mask cma__t_mask; +typedef fd_set cma__t_file_mask; + + +/* + * GLOBAL DATA + */ + +/* + * Maximum number of files (ie, max_fd+1) as determined by getdtablesize(). + */ +extern int cma__g_mx_file; + +/* + * Number of submasks (ie "int" sized chunks) per file descriptor mask as + * determined by getdtablesize(). + */ +extern int cma__g_nspm; + +/* + * MACROS + */ + +/* + * Define a constant for the errno value which indicates that the requested + * operation was not performed because it would block the process. + */ +# define cma__is_blocking(s) \ + ((s == EAGAIN) || (s == EWOULDBLOCK) || (s == EINPROGRESS) || \ + (s == EALREADY) || (s == EDEADLK)) + +/* +* It is necessary to issue an I/O function, before calling cma__io_wait() +* in the following cases: +* +* * This file descriptor has been set non-blocking by CMA +* * This file descriptor has been set non-blocking by the user. +*/ + +#define cma__issue_io_call(fd) \ + ( (cma__g_file[fd]->non_blocking) || \ + (cma__g_file[fd]->user_fl.user_non_blocking) ) + + +#define cma__set_user_nonblocking(flags) \ + +/* + * Determine if the file is open + */ +/* + * If the file gets closed while waiting for the mutex cma__g_file[rfd] + * gets set to null. This results in a crash if NDEBUG is set to 0 + * since cma__int_lock tries to dereference it to set the mutex ownership + * after it gets the mutex. The following will still set the ownership + * in cma__int_lock so we'll set it back to noone if cma__g_file is null + * when we come back just in case it matters. It shouldn't since its no + * longer in use but..... + * Callers of this should recheck cma__g_file after the reservation to + * make sure continueing makes sense. + */ +#define cma__fd_reserve(rfd) \ + { \ + cma__t_int_mutex *__mutex__; \ + __mutex__ = cma__g_file[rfd]->mutex; \ + cma__int_lock (__mutex__); \ + if(cma__g_file[rfd] == (cma__t_file_obj *)cma_c_null_ptr) \ + cma__int_unlock(__mutex__); \ + } + + +/* + * Unreserve a file descriptor + */ +#define cma__fd_unreserve(ufd) cma__int_unlock (cma__g_file[ufd]->mutex) + +/* + * AND together two select file descriptor masks + */ +#define cma__fdm_and(target,a,b) \ + { \ + int __i__ = cma__g_nspm; \ + while (__i__--) \ + (target)->fds_bits[__i__] = \ + (a)->fds_bits[__i__] & (b)->fds_bits[__i__]; \ + } + +/* + * Clear a bit in a select file descriptor mask + * + * FD_CLR(n, p) := ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) + */ +#define cma__fdm_clr_bit(n,p) FD_CLR (n, p) + +/* + * Copy the contents of one file descriptor mask into another. If the + * destination operand is null, do nothing; if the source operand is null, + * simply zero the destination. + */ +#define cma__fdm_copy(src,dst,nfds) { \ + if (dst) \ + if (src) { \ + cma__t_mask *__s__ = (cma__t_mask *)(src); \ + cma__t_mask *__d__ = (cma__t_mask *)(dst); \ + int __i__; \ + for (__i__ = 0; __i__ < (nfds); __i__ += cma__c_nbpm) \ + *__d__++ = *__s__++; \ + } \ + else \ + cma__fdm_zero (dst); \ + } + +/* + * To increment count for each bit set in fd - mask + */ +#define cma__fdm_count_bits(map,count) \ + { \ + int __i__ = cma__g_nspm; \ + while (__i__--) { \ + cma__t_mask __tm__; \ + __tm__ = (map)->fds_bits[__i__]; \ + while(__tm__) { \ + (count)++; \ + __tm__ &= ~(__tm__ & (-__tm__)); /* Assumes 2's comp */ \ + } \ + } \ + } + +/* + * Test if a bit is set in a select file descriptor mask + * + * FD_ISSET(n,p) := ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) + */ +#define cma__fdm_is_set(n,p) FD_ISSET (n, p) + +/* + * OR together two select file descriptor masks + */ +#define cma__fdm_or(target,a,b) \ + { \ + int __i__ = cma__g_nspm; \ + while (__i__--) \ + (target)->fds_bits[__i__] = \ + (a)->fds_bits[__i__] | (b)->fds_bits[__i__]; \ + } + +/* + * Set a bit in a select file descriptor mask + * + * FD_SET(n,p) := ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) + */ +#define cma__fdm_set_bit(n,p) FD_SET (n, p) + +/* + * Clear a select file descriptor mask. + */ +#define cma__fdm_zero(n) \ + cma__memset ((char *) n, 0, cma__g_nspm * sizeof(cma__t_mask)) + + + +/* + * CMA "thread-synchronous" I/O read/write operations + */ + + /* + * Since all CMA "thread-synchronous" I/O (read or write) operations on + * U*ix follow the exact same structure, the wrapper routines have been + * condensed into a macro. + * + * The steps performed are as follows: + * 1. Check that the file descriptor is a legitimate value. + * 2. Check that the entry in the CMA file "database" which corresponds to + * the file descriptor indicates that the "file" was "opened" by CMA. + * 3. Reserve the file, to serialized access to files. This not only + * simplifies things, but also defends against non-reentrancy. + * 4. If the "file" is "set" for non-blocking I/O, check if we + * have actually set the file non-blocking yet, and if not do so. + * Then, issue the I/O operantion. + * Success or failure is returned immediately, after unreserving the + * file. If the error indicates that the operation would have caused + * the process to block, continue to the next step. + * 5. The I/O prolog adds this "file" to the global bit mask, which + * represents all "files" which have threads waiting to perform I/O on + * them, and causes the thread to block on the condition variable for + * this "file". Periodically, a select is done on this global bit + * mask, and the condition variables corresponding to "files" which + * are ready for I/O are signaled, releasing those waiting threads to + * perform their I/O. + * 6. When the thread returns from the I/O prolog, it can (hopefully) + * perform its operation without blocking the process. + * 7. The I/O epilog clears the bit in the global mask and/or signals the + * the next thread waiting for this "file", as appropriate. + * 8. If the I/O failed, continue to loop. + * 9. Finally, the "file" is unreserved, as we're done with it, and the + * result of the operation is returned. + * + * + * Note: currently, we believe that timeslicing which is based on the + * virtual-time timer does not cause system calls to return EINTR. + * Threfore, any EINTR returns are relayed directly to the caller. + * On platforms which do not support a virtual-time timer, the code + * should probably catch EINTR returns and restart the system call. + */ + +/* + * This macro is used for both read-type and write-type functions. + * + * Note: the second call to "func" may require being bracketed in a + * cma__interrupt_disable/cma__interrupt_enable pair, but we'll + * wait and see if this is necessary. + */ +#define cma__ts_func(func,fd,arglist,type,post_process) { \ + cma_t_integer __res__; \ + cma_t_boolean __done__ = cma_c_false; \ + if ((fd < 0) || (fd >= cma__g_mx_file)) return (cma__set_errno (EBADF), -1); \ + if (!cma__is_open(fd)) return (cma__set_errno (EBADF), -1); \ + cma__fd_reserve (fd); \ + if (!cma__is_open(fd)) return (cma__set_errno (EBADF), -1); \ + if (cma__issue_io_call(fd)) {\ + if ((!cma__g_file[fd]->set_non_blocking) && \ + (cma__g_file[fd]->non_blocking == cma_c_true)) \ + cma__set_nonblocking(fd); \ + cma__interrupt_disable (0); \ + TRY { \ + __res__ = func arglist; \ + } \ + CATCH_ALL { \ + cma__interrupt_enable (0); \ + cma__fd_unreserve (fd); \ + RERAISE; \ + } \ + ENDTRY \ + cma__interrupt_enable (0); \ + if ((__res__ != -1) \ + || (!cma__is_blocking (errno)) \ + || (cma__g_file[fd]->user_fl.user_non_blocking)) \ + __done__ = cma_c_true; \ + } \ + if (__done__) { \ + cma__fd_unreserve (fd); \ + } \ + else { \ + TRY { \ + cma__io_prolog (type, fd); \ + while (!__done__) { \ + cma__io_wait (type, fd); \ + __res__ = func arglist; \ + if ((__res__ != -1) \ + || (!cma__is_blocking (errno)) \ + || (cma__g_file[fd]->user_fl.user_non_blocking)) \ + __done__ = cma_c_true; \ + } \ + } \ + FINALLY { \ + cma__io_epilog (type, fd); \ + cma__fd_unreserve (fd); \ + } \ + ENDTRY \ + } \ + if (__res__ != -1) post_process; \ + return __res__; \ + } + + /* + * Since most CMA "thread-synchronous" I/O ("open"-type) operations on + * U*ix follow the exact same structure, the wrapper routines have been + * condensed into a macro. + * + * The steps performed are as follows: + * 1. Issue the open function. + * 2. If the value returned indicates an error, return it to the caller. + * 3. If the file descriptor returned is larger than what we think is the + * maximum value (ie if it is too big for our database) then bugcheck. + * 4. "Open" the "file" in the CMA file database. + * 5. Return the file descriptor value to the caller. + * + * FIX-ME: for the time being, if the I/O operation returns EINTR, we + * simply return it to the caller; eventually, we should catch this + * and "do the right thing" (if we can figure out what that is). + */ + +/* + * This macro is used for all "open"-type functions which return a single file + * desciptor by immediate value. + */ +#define cma__ts_open(func,arglist,post_process) { \ + int __fd__; \ + TRY { \ + cma__int_init (); \ + cma__int_lock (cma__g_io_data_mutex); \ + __fd__ = func arglist; \ + cma__int_unlock (cma__g_io_data_mutex); \ + if (__fd__ >= 0 && __fd__ < cma__g_mx_file) \ + post_process; \ + } \ + CATCH_ALL \ + { \ + cma__set_errno (EBADF); \ + __fd__ = -1; \ + } \ + ENDTRY \ + if (__fd__ >= cma__g_mx_file) \ + cma__bugcheck ("cma__ts_open: fd is too large"); \ + return __fd__; \ + } +/* + * This macro is used for all "open"-type functions which return a pair of file + * desciptors by reference parameter. + */ +#define cma__ts_open2(func,fdpair,arglist,post_process) { \ + int __res__; \ + TRY { \ + cma__int_init (); \ + cma__int_lock (cma__g_io_data_mutex); \ + __res__ = func arglist; \ + cma__int_unlock (cma__g_io_data_mutex); \ + if (__res__ >= 0 && fdpair[0] < cma__g_mx_file \ + && fdpair[1] < cma__g_mx_file) \ + post_process; \ + } \ + CATCH_ALL \ + { \ + cma__set_errno (EBADF); \ + __res__ = -1; \ + } \ + ENDTRY \ + if ((fdpair[0] >= cma__g_mx_file) || (fdpair[1] >= cma__g_mx_file)) \ + cma__bugcheck ("cma__ts_open2: one of fd's is too large"); \ + return __res__; \ + } + +/* + * INTERNAL INTERFACES + */ +extern void cma__close_general (int); + +extern void cma__init_thread_io (void); + +extern cma_t_boolean cma__io_available (cma__t_io_type,int,struct timeval *); + +extern void cma__io_epilog (cma__t_io_type,int); + +extern void cma__io_prolog (cma__t_io_type,int); + +extern void cma__io_wait (cma__t_io_type,int); + +extern void cma__open_general (int); + +extern void cma__reinit_thread_io (int); + +extern void cma__set_nonblocking (int); + +extern void cma__set_user_nonblock_flags (int,int); + +extern cma_t_boolean cma__is_open (int); + + +#endif diff --git a/gdb/osf-share/HP800/.Sanitize b/gdb/osf-share/HP800/.Sanitize new file mode 100644 index 0000000000..17e13893f1 --- /dev/null +++ b/gdb/osf-share/HP800/.Sanitize @@ -0,0 +1,44 @@ +# .Sanitize for devo/gdb/osf-share/HP800. + +# Each directory to survive its way into a release will need a file +# like this one called "./.Sanitize". All keyword lines must exist, +# and must exist in the order specified by this file. Each directory +# in the tree will be processed, top down, in the following order. + +# Hash started lines like this one are comments and will be deleted +# before anything else is done. Blank lines will also be squashed +# out. + +# The lines between the "Do-first:" line and the "Things-to-keep:" +# line are executed as a /bin/sh shell script before anything else is +# done in this directory. + +Do-first: + +# All files listed between the "Things-to-keep:" line and the +# "Files-to-sed:" line will be kept. All other files will be removed. +# Directories listed in this section will have their own Sanitize +# called. Directories not listed will be removed in their entirety +# with rm -rf. + +Things-to-keep: + +cma_thread_io.h + +# Things which are explicitly *not* kept, for now. + +Things-to-lose: + +Do-last: + +# Don't try to clean directories here, as the 'mv' command will fail. +# Also, grep fails on NFS mounted directories. + +for i in * ; do + if test ! -d $i && (grep sanitize $i > /dev/null) ; then + echo '***' Some mentions of Sanitize are still left in $i! 1>&2 + fi +done + +# +# End of file. diff --git a/gdb/osf-share/HP800/cma_thread_io.h b/gdb/osf-share/HP800/cma_thread_io.h new file mode 100644 index 0000000000..e9bef3be45 --- /dev/null +++ b/gdb/osf-share/HP800/cma_thread_io.h @@ -0,0 +1,432 @@ +/* + * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC. + * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY + * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION + * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems + * To anyone who acknowledges that this file is provided "AS IS" without + * any express or implied warranty: permission to use, copy, modify, and + * distribute this file for any purpose is hereby granted without fee, + * provided that the above copyright notices and this notice appears in + * all source code copies, and that none of the names listed above be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. None of these organizations + * makes any representations about the suitability of this software for + * any purpose. + */ +/* + * + * Header file for thread synchrounous I/O + */ + +#ifndef CMA_THREAD_IO +#define CMA_THREAD_IO + +/* + * INCLUDE FILES + */ + +#include <cma_config.h> +#include <sys/file.h> +#include <cma.h> +#include <sys/types.h> +#include <sys/time.h> +#include <cma_init.h> +#include <cma_errors.h> + +/* + * CONSTANTS + */ + + + +/* + * Maximum number of files (ie, max_fd+1) + */ +#define cma__c_mx_file FD_SETSIZE + +/* + * Number of bits per file descriptor bit mask (ie number of bytes * bits/byte) + */ +#define cma__c_nbpm NFDBITS + +/* + * TYPE DEFINITIONS + */ + +typedef enum CMA__T_IO_TYPE { + cma__c_io_read = 0, + cma__c_io_write = 1, + cma__c_io_except = 2 + } cma__t_io_type; +#define cma__c_max_io_type 2 + +/* + * From our local <sys/types.h>: + * + * typedef long fd_mask; + * + * typedef struct fd_set { + * fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)]; + * } fd_set; + * + */ +typedef fd_mask cma__t_mask; +typedef fd_set cma__t_file_mask; + + + +/* + * GLOBAL DATA + */ + +/* + * Maximum number of files (ie, max_fd+1) as determined by getdtablesize(). + */ +extern int cma__g_mx_file; + +/* + * Number of submasks (ie "int" sized chunks) per file descriptor mask as + * determined by getdtablesize(). + */ +extern int cma__g_nspm; + +/* + * MACROS + */ + +/* + * Define a constant for the errno value which indicates that the requested + * operation was not performed because it would block the process. + */ +# define cma__is_blocking(s) \ + ((s == EAGAIN) || (s == EWOULDBLOCK) || (s == EINPROGRESS) || \ + (s == EALREADY) || (s == EDEADLK)) + +/* +* It is necessary to issue an I/O function, before calling cma__io_wait() +* in the following cases: +* +* * This file descriptor has been set non-blocking by CMA +* * This file descriptor has been set non-blocking by the user. +*/ + +#define cma__issue_io_call(fd) \ + ( (cma__g_file[fd]->non_blocking) || \ + (cma__g_file[fd]->user_fl.user_non_blocking) ) + + +#define cma__set_user_nonblocking(flags) \ + +/* + * Determine if the file is open + */ +/* + * If the file gets closed while waiting for the mutex cma__g_file[rfd] + * gets set to null. This results in a crash if NDEBUG is set to 0 + * since cma__int_lock tries to dereference it to set the mutex ownership + * after it gets the mutex. The following will still set the ownership + * in cma__int_lock so we'll set it back to noone if cma__g_file is null + * when we come back just in case it matters. It shouldn't since its no + * longer in use but..... + * Callers of this should recheck cma__g_file after the reservation to + * make sure continueing makes sense. + */ +#define cma__fd_reserve(rfd) \ + { \ + cma__t_int_mutex *__mutex__; \ + __mutex__ = cma__g_file[rfd]->mutex; \ + cma__int_lock (__mutex__); \ + if(cma__g_file[rfd] == (cma__t_file_obj *)cma_c_null_ptr) \ + cma__int_unlock(__mutex__); \ + } + + +/* + * Unreserve a file descriptor + */ +#define cma__fd_unreserve(ufd) cma__int_unlock (cma__g_file[ufd]->mutex) + +/* + * AND together two select file descriptor masks + */ +#define cma__fdm_and(target,a,b) \ + { \ + int __i__ = cma__g_nspm; \ + while (__i__--) \ + (target)->fds_bits[__i__] = \ + (a)->fds_bits[__i__] & (b)->fds_bits[__i__]; \ + } + +/* + * Clear a bit in a select file descriptor mask + * + * FD_CLR(n, p) := ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) + */ +#define cma__fdm_clr_bit(n,p) FD_CLR (n, p) + +/* + * Copy the contents of one file descriptor mask into another. If the + * destination operand is null, do nothing; if the source operand is null, + * simply zero the destination. + */ +#define cma__fdm_copy(src,dst,nfds) { \ + if (dst) \ + if (src) { \ + cma__t_mask *__s__ = (cma__t_mask *)(src); \ + cma__t_mask *__d__ = (cma__t_mask *)(dst); \ + int __i__; \ + for (__i__ = 0; __i__ < (nfds); __i__ += cma__c_nbpm) \ + *__d__++ = *__s__++; \ + } \ + else \ + cma__fdm_zero (dst); \ + } + +/* + * To increment count for each bit set in fd - mask + */ +#define cma__fdm_count_bits(map,count) \ + { \ + int __i__ = cma__g_nspm; \ + while (__i__--) { \ + cma__t_mask __tm__; \ + __tm__ = (map)->fds_bits[__i__]; \ + while(__tm__) { \ + (count)++; \ + __tm__ &= ~(__tm__ & (-__tm__)); /* Assumes 2's comp */ \ + } \ + } \ + } + +/* + * Test if a bit is set in a select file descriptor mask + * + * FD_ISSET(n,p) := ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) + */ +#define cma__fdm_is_set(n,p) FD_ISSET (n, p) + +/* + * OR together two select file descriptor masks + */ +#define cma__fdm_or(target,a,b) \ + { \ + int __i__ = cma__g_nspm; \ + while (__i__--) \ + (target)->fds_bits[__i__] = \ + (a)->fds_bits[__i__] | (b)->fds_bits[__i__]; \ + } + +/* + * Set a bit in a select file descriptor mask + * + * FD_SET(n,p) := ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) + */ +#define cma__fdm_set_bit(n,p) FD_SET (n, p) + +/* + * Clear a select file descriptor mask. + */ +#define cma__fdm_zero(n) \ + cma__memset ((char *) n, 0, cma__g_nspm * sizeof(cma__t_mask)) + + + + + +/* + * CMA "thread-synchronous" I/O read/write operations + */ + + /* + * Since all CMA "thread-synchronous" I/O (read or write) operations on + * U*ix follow the exact same structure, the wrapper routines have been + * condensed into a macro. + * + * The steps performed are as follows: + * 1. Check that the file descriptor is a legitimate value. + * 2. Check that the entry in the CMA file "database" which corresponds to + * the file descriptor indicates that the "file" was "opened" by CMA. + * 3. Reserve the file, to serialized access to files. This not only + * simplifies things, but also defends against non-reentrancy. + * 4. If the "file" is "set" for non-blocking I/O, check if we + * have actually set the file non-blocking yet, and if not do so. + * Then, issue the I/O operantion. + * Success or failure is returned immediately, after unreserving the + * file. If the error indicates that the operation would have caused + * the process to block, continue to the next step. + * 5. The I/O prolog adds this "file" to the global bit mask, which + * represents all "files" which have threads waiting to perform I/O on + * them, and causes the thread to block on the condition variable for + * this "file". Periodically, a select is done on this global bit + * mask, and the condition variables corresponding to "files" which + * are ready for I/O are signaled, releasing those waiting threads to + * perform their I/O. + * 6. When the thread returns from the I/O prolog, it can (hopefully) + * perform its operation without blocking the process. + * 7. The I/O epilog clears the bit in the global mask and/or signals the + * the next thread waiting for this "file", as appropriate. + * 8. If the I/O failed, continue to loop. + * 9. Finally, the "file" is unreserved, as we're done with it, and the + * result of the operation is returned. + * + * + * Note: currently, we believe that timeslicing which is based on the + * virtual-time timer does not cause system calls to return EINTR. + * Threfore, any EINTR returns are relayed directly to the caller. + * On platforms which do not support a virtual-time timer, the code + * should probably catch EINTR returns and restart the system call. + */ + +/* + * This macro is used for both read-type and write-type functions. + * + * Note: the second call to "func" may require being bracketed in a + * cma__interrupt_disable/cma__interrupt_enable pair, but we'll + * wait and see if this is necessary. + */ +#define cma__ts_func(func,fd,arglist,type,post_process) { \ + cma_t_integer __res__; \ + cma_t_boolean __done__ = cma_c_false; \ + if ((fd < 0) || (fd >= cma__g_mx_file)) return (cma__set_errno (EBADF), -1); \ + if (!cma__is_open(fd)) return (cma__set_errno (EBADF), -1); \ + cma__fd_reserve (fd); \ + if (!cma__is_open(fd)) return (cma__set_errno (EBADF), -1); \ + if (cma__issue_io_call(fd)) {\ + if ((!cma__g_file[fd]->set_non_blocking) && \ + (cma__g_file[fd]->non_blocking == cma_c_true)) \ + cma__set_nonblocking(fd); \ + cma__interrupt_disable (0); \ + TRY { \ + __res__ = func arglist; \ + } \ + CATCH_ALL { \ + cma__interrupt_enable (0); \ + cma__fd_unreserve (fd); \ + RERAISE; \ + } \ + ENDTRY \ + cma__interrupt_enable (0); \ + if ((__res__ != -1) \ + || (!cma__is_blocking (errno)) \ + || (cma__g_file[fd]->user_fl.user_non_blocking)) \ + __done__ = cma_c_true; \ + } \ + if (__done__) { \ + cma__fd_unreserve (fd); \ + } \ + else { \ + TRY { \ + cma__io_prolog (type, fd); \ + while (!__done__) { \ + cma__io_wait (type, fd); \ + __res__ = func arglist; \ + if ((__res__ != -1) \ + || (!cma__is_blocking (errno)) \ + || (cma__g_file[fd]->user_fl.user_non_blocking)) \ + __done__ = cma_c_true; \ + } \ + } \ + FINALLY { \ + cma__io_epilog (type, fd); \ + cma__fd_unreserve (fd); \ + } \ + ENDTRY \ + } \ + if (__res__ != -1) post_process; \ + return __res__; \ + } + + /* + * Since most CMA "thread-synchronous" I/O ("open"-type) operations on + * U*ix follow the exact same structure, the wrapper routines have been + * condensed into a macro. + * + * The steps performed are as follows: + * 1. Issue the open function. + * 2. If the value returned indicates an error, return it to the caller. + * 3. If the file descriptor returned is larger than what we think is the + * maximum value (ie if it is too big for our database) then bugcheck. + * 4. "Open" the "file" in the CMA file database. + * 5. Return the file descriptor value to the caller. + * + * FIX-ME: for the time being, if the I/O operation returns EINTR, we + * simply return it to the caller; eventually, we should catch this + * and "do the right thing" (if we can figure out what that is). + */ + +/* + * This macro is used for all "open"-type functions which return a single file + * desciptor by immediate value. + */ +#define cma__ts_open(func,arglist,post_process) { \ + int __fd__; \ + TRY { \ + cma__int_init (); \ + cma__int_lock (cma__g_io_data_mutex); \ + __fd__ = func arglist; \ + cma__int_unlock (cma__g_io_data_mutex); \ + if (__fd__ >= 0 && __fd__ < cma__g_mx_file) \ + post_process; \ + } \ + CATCH_ALL \ + { \ + cma__set_errno (EBADF); \ + __fd__ = -1; \ + } \ + ENDTRY \ + if (__fd__ >= cma__g_mx_file) \ + cma__bugcheck ("cma__ts_open: fd is too large"); \ + return __fd__; \ + } +/* + * This macro is used for all "open"-type functions which return a pair of file + * desciptors by reference parameter. + */ +#define cma__ts_open2(func,fdpair,arglist,post_process) { \ + int __res__; \ + TRY { \ + cma__int_init (); \ + cma__int_lock (cma__g_io_data_mutex); \ + __res__ = func arglist; \ + cma__int_unlock (cma__g_io_data_mutex); \ + if (__res__ >= 0 && fdpair[0] < cma__g_mx_file \ + && fdpair[1] < cma__g_mx_file) \ + post_process; \ + } \ + CATCH_ALL \ + { \ + cma__set_errno (EBADF); \ + __res__ = -1; \ + } \ + ENDTRY \ + if ((fdpair[0] >= cma__g_mx_file) || (fdpair[1] >= cma__g_mx_file)) \ + cma__bugcheck ("cma__ts_open2: one of fd's is too large"); \ + return __res__; \ + } + +/* + * INTERNAL INTERFACES + */ +extern void cma__close_general (int); + +extern void cma__init_thread_io (void); + +extern cma_t_boolean cma__io_available (cma__t_io_type,int,struct timeval *); + +extern void cma__io_epilog (cma__t_io_type,int); + +extern void cma__io_prolog (cma__t_io_type,int); + +extern void cma__io_wait (cma__t_io_type,int); + +extern void cma__open_general (int); + +extern void cma__reinit_thread_io (int); + +extern void cma__set_nonblocking (int); + +extern void cma__set_user_nonblock_flags (int,int); + +extern cma_t_boolean cma__is_open (int); + +#endif diff --git a/gdb/osf-share/README b/gdb/osf-share/README new file mode 100644 index 0000000000..c6d2e0fb53 --- /dev/null +++ b/gdb/osf-share/README @@ -0,0 +1,8 @@ +This directory contains header files necessary to build a thread-aware GDB on +systems based on OSF's CMA threads package. + +The latest version of these header files are available for free from: + + http://www.osf.org/mall/dce/SW-code + +Currently, the only port of GDB which supports CMA threads is HP/UX-10.10. diff --git a/gdb/osf-share/RIOS/.Sanitize b/gdb/osf-share/RIOS/.Sanitize new file mode 100644 index 0000000000..3820304411 --- /dev/null +++ b/gdb/osf-share/RIOS/.Sanitize @@ -0,0 +1,44 @@ +# .Sanitize for devo/gdb/osf-share/RIOS. + +# Each directory to survive its way into a release will need a file +# like this one called "./.Sanitize". All keyword lines must exist, +# and must exist in the order specified by this file. Each directory +# in the tree will be processed, top down, in the following order. + +# Hash started lines like this one are comments and will be deleted +# before anything else is done. Blank lines will also be squashed +# out. + +# The lines between the "Do-first:" line and the "Things-to-keep:" +# line are executed as a /bin/sh shell script before anything else is +# done in this directory. + +Do-first: + +# All files listed between the "Things-to-keep:" line and the +# "Files-to-sed:" line will be kept. All other files will be removed. +# Directories listed in this section will have their own Sanitize +# called. Directories not listed will be removed in their entirety +# with rm -rf. + +Things-to-keep: + +cma_thread_io.h + +# Things which are explicitly *not* kept, for now. + +Things-to-lose: + +Do-last: + +# Don't try to clean directories here, as the 'mv' command will fail. +# Also, grep fails on NFS mounted directories. + +for i in * ; do + if test ! -d $i && (grep sanitize $i > /dev/null) ; then + echo '***' Some mentions of Sanitize are still left in $i! 1>&2 + fi +done + +# +# End of file. diff --git a/gdb/osf-share/RIOS/cma_thread_io.h b/gdb/osf-share/RIOS/cma_thread_io.h new file mode 100644 index 0000000000..98117caf7d --- /dev/null +++ b/gdb/osf-share/RIOS/cma_thread_io.h @@ -0,0 +1,434 @@ +/* + * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC. + * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY + * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION + * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems + * To anyone who acknowledges that this file is provided "AS IS" without + * any express or implied warranty: permission to use, copy, modify, and + * distribute this file for any purpose is hereby granted without fee, + * provided that the above copyright notices and this notice appears in + * all source code copies, and that none of the names listed above be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. None of these organizations + * makes any representations about the suitability of this software for + * any purpose. + */ +/* + * Header file for thread synchrounous I/O + */ + +#ifndef CMA_THREAD_IO +#define CMA_THREAD_IO + +/* + * INCLUDE FILES + */ + +#include <cma_config.h> +#include <sys/select.h> +#include <cma.h> +#include <sys/types.h> +#include <sys/time.h> +#include <cma_init.h> +#include <cma_errors.h> + +/* + * CONSTANTS + */ + +/* + * Maximum number of files (ie, max_fd+1) + */ +#define cma__c_mx_file FD_SETSIZE + +/* + * Number of bits per file descriptor bit mask (ie number of bytes * bits/byte) + */ +#define cma__c_nbpm NFDBITS + +/* + * TYPE DEFINITIONS + */ + +typedef enum CMA__T_IO_TYPE { + cma__c_io_read = 0, + cma__c_io_write = 1, + cma__c_io_except = 2 + } cma__t_io_type; +#define cma__c_max_io_type 2 + +/* + * From our local <sys/types.h>: + * + * typedef long fd_mask; + * + * typedef struct fd_set { + * fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)]; + * } fd_set; + * + */ +typedef fd_mask cma__t_mask; +typedef fd_set cma__t_file_mask; + + + +/* + * GLOBAL DATA + */ + +/* + * Maximum number of files (ie, max_fd+1) as determined by getdtablesize(). + */ +extern int cma__g_mx_file; + +/* + * Number of submasks (ie "int" sized chunks) per file descriptor mask as + * determined by getdtablesize(). + */ +extern int cma__g_nspm; + +/* + * MACROS + */ + +/* + * Define a constant for the errno value which indicates that the requested + * operation was not performed because it would block the process. + */ +# define cma__is_blocking(s) \ + ((s == EAGAIN) || (s == EWOULDBLOCK) || (s == EINPROGRESS) || \ + (s == EALREADY) || (s == EDEADLK)) + +/* +* It is necessary to issue an I/O function, before calling cma__io_wait() +* in the following cases: +* +* * This file descriptor has been set non-blocking by CMA +* * This file descriptor has been set non-blocking by the user. +*/ + +#define cma__issue_io_call(fd) \ + ( (cma__g_file[fd]->non_blocking) || \ + (cma__g_file[fd]->user_fl.user_non_blocking) ) + + +#define cma__set_user_nonblocking(flags) \ + +/* + * Determine if the file is open + */ +/* + * If the file gets closed while waiting for the mutex cma__g_file[rfd] + * gets set to null. This results in a crash if NDEBUG is set to 0 + * since cma__int_lock tries to dereference it to set the mutex ownership + * after it gets the mutex. The following will still set the ownership + * in cma__int_lock so we'll set it back to noone if cma__g_file is null + * when we come back just in case it matters. It shouldn't since its no + * longer in use but..... + * Callers of this should recheck cma__g_file after the reservation to + * make sure continueing makes sense. + */ +#define cma__fd_reserve(rfd) \ + { \ + cma__t_int_mutex *__mutex__; \ + __mutex__ = cma__g_file[rfd]->mutex; \ + cma__int_lock (__mutex__); \ + if(cma__g_file[rfd] == (cma__t_file_obj *)cma_c_null_ptr) \ + cma__int_unlock(__mutex__); \ + } + + +/* + * Unreserve a file descriptor + */ +#define cma__fd_unreserve(ufd) cma__int_unlock (cma__g_file[ufd]->mutex) + +/* + * AND together two select file descriptor masks + */ +#define cma__fdm_and(target,a,b) \ + { \ + int __i__ = cma__g_nspm; \ + while (__i__--) \ + (target)->fds_bits[__i__] = \ + (a)->fds_bits[__i__] & (b)->fds_bits[__i__]; \ + } + +/* + * Clear a bit in a select file descriptor mask + * + * FD_CLR(n, p) := ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) + */ +#define cma__fdm_clr_bit(n,p) FD_CLR (n, p) + +/* + * Copy the contents of one file descriptor mask into another. If the + * destination operand is null, do nothing; if the source operand is null, + * simply zero the destination. + */ +#define cma__fdm_copy(src,dst,nfds) { \ + if (dst) \ + if (src) { \ + cma__t_mask *__s__ = (cma__t_mask *)(src); \ + cma__t_mask *__d__ = (cma__t_mask *)(dst); \ + int __i__; \ + for (__i__ = 0; __i__ < (nfds); __i__ += cma__c_nbpm) \ + *__d__++ = *__s__++; \ + } \ + else \ + cma__fdm_zero (dst); \ + } + +/* + * To increment count for each bit set in fd - mask + */ +#define cma__fdm_count_bits(map,count) \ + { \ + int __i__ = cma__g_nspm; \ + while (__i__--) { \ + cma__t_mask __tm__; \ + __tm__ = (map)->fds_bits[__i__]; \ + while(__tm__) { \ + (count)++; \ + __tm__ &= ~(__tm__ & (-__tm__)); /* Assumes 2's comp */ \ + } \ + } \ + } + +/* + * Test if a bit is set in a select file descriptor mask + * + * FD_ISSET(n,p) := ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) + */ +#define cma__fdm_is_set(n,p) FD_ISSET (n, p) + +/* + * OR together two select file descriptor masks + */ +#define cma__fdm_or(target,a,b) \ + { \ + int __i__ = cma__g_nspm; \ + while (__i__--) \ + (target)->fds_bits[__i__] = \ + (a)->fds_bits[__i__] | (b)->fds_bits[__i__]; \ + } + +/* + * Set a bit in a select file descriptor mask + * + * FD_SET(n,p) := ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) + */ +#define cma__fdm_set_bit(n,p) FD_SET (n, p) + +/* + * Clear a select file descriptor mask. + */ +#define cma__fdm_zero(n) \ + cma__memset ((char *) n, 0, cma__g_nspm * sizeof(cma__t_mask)) + + + + + +/* + * CMA "thread-synchronous" I/O read/write operations + */ + + /* + * Since all CMA "thread-synchronous" I/O (read or write) operations on + * U*ix follow the exact same structure, the wrapper routines have been + * condensed into a macro. + * + * The steps performed are as follows: + * 1. Check that the file descriptor is a legitimate value. + * 2. Check that the entry in the CMA file "database" which corresponds to + * the file descriptor indicates that the "file" was "opened" by CMA. + * 3. Reserve the file, to serialized access to files. This not only + * simplifies things, but also defends against non-reentrancy. + * 4. If the "file" is "set" for non-blocking I/O, check if we + * have actually set the file non-blocking yet, and if not do so. + * Then, issue the I/O operantion. + * Success or failure is returned immediately, after unreserving the + * file. If the error indicates that the operation would have caused + * the process to block, continue to the next step. + * 5. The I/O prolog adds this "file" to the global bit mask, which + * represents all "files" which have threads waiting to perform I/O on + * them, and causes the thread to block on the condition variable for + * this "file". Periodically, a select is done on this global bit + * mask, and the condition variables corresponding to "files" which + * are ready for I/O are signaled, releasing those waiting threads to + * perform their I/O. + * 6. When the thread returns from the I/O prolog, it can (hopefully) + * perform its operation without blocking the process. + * 7. The I/O epilog clears the bit in the global mask and/or signals the + * the next thread waiting for this "file", as appropriate. + * 8. If the I/O failed, continue to loop. + * 9. Finally, the "file" is unreserved, as we're done with it, and the + * result of the operation is returned. + * + * + * Note: currently, we believe that timeslicing which is based on the + * virtual-time timer does not cause system calls to return EINTR. + * Threfore, any EINTR returns are relayed directly to the caller. + * On platforms which do not support a virtual-time timer, the code + * should probably catch EINTR returns and restart the system call. + */ + +/* + * This macro is used for both read-type and write-type functions. + * + * Note: the second call to "func" may require being bracketed in a + * cma__interrupt_disable/cma__interrupt_enable pair, but we'll + * wait and see if this is necessary. + */ +#define cma__ts_func(func,fd,arglist,type,post_process) { \ + cma_t_integer __res__; \ + cma_t_boolean __done__ = cma_c_false; \ + if ((fd < 0) || (fd >= cma__g_mx_file)) return (cma__set_errno (EBADF), -1); \ + if (!cma__is_open(fd)) return (cma__set_errno (EBADF), -1); \ + cma__fd_reserve (fd); \ + if (!cma__is_open(fd)) return (cma__set_errno (EBADF), -1); \ + if (cma__issue_io_call(fd)) {\ + if ((!cma__g_file[fd]->set_non_blocking) && \ + (cma__g_file[fd]->non_blocking == cma_c_true)) \ + cma__set_nonblocking(fd); \ + cma__interrupt_disable (0); \ + TRY { \ + __res__ = func arglist; \ + } \ + CATCH_ALL { \ + cma__interrupt_enable (0); \ + cma__fd_unreserve (fd); \ + RERAISE; \ + } \ + ENDTRY \ + cma__interrupt_enable (0); \ + if ((__res__ != -1) \ + || (!cma__is_blocking (errno)) \ + || (cma__g_file[fd]->user_fl.user_non_blocking)) \ + __done__ = cma_c_true; \ + } \ + if (__done__) { \ + cma__fd_unreserve (fd); \ + } \ + else { \ + TRY { \ + cma__io_prolog (type, fd); \ + while (!__done__) { \ + cma__io_wait (type, fd); \ + __res__ = func arglist; \ + if ((__res__ != -1) \ + || (!cma__is_blocking (errno)) \ + || (cma__g_file[fd]->user_fl.user_non_blocking)) \ + __done__ = cma_c_true; \ + } \ + } \ + FINALLY { \ + cma__io_epilog (type, fd); \ + cma__fd_unreserve (fd); \ + } \ + ENDTRY \ + } \ + if (__res__ != -1) post_process; \ + return __res__; \ + } + + /* + * Since most CMA "thread-synchronous" I/O ("open"-type) operations on + * U*ix follow the exact same structure, the wrapper routines have been + * condensed into a macro. + * + * The steps performed are as follows: + * 1. Issue the open function. + * 2. If the value returned indicates an error, return it to the caller. + * 3. If the file descriptor returned is larger than what we think is the + * maximum value (ie if it is too big for our database) then bugcheck. + * 4. "Open" the "file" in the CMA file database. + * 5. Return the file descriptor value to the caller. + * + * FIX-ME: for the time being, if the I/O operation returns EINTR, we + * simply return it to the caller; eventually, we should catch this + * and "do the right thing" (if we can figure out what that is). + */ + +/* + * This macro is used for all "open"-type functions which return a single file + * desciptor by immediate value. + */ +#define cma__ts_open(func,arglist,post_process) { \ + int __fd__; \ + TRY { \ + cma__int_init (); \ + cma__int_lock (cma__g_io_data_mutex); \ + __fd__ = func arglist; \ + cma__int_unlock (cma__g_io_data_mutex); \ + if (__fd__ >= 0 && __fd__ < cma__g_mx_file) \ + post_process; \ + } \ + CATCH_ALL \ + { \ + cma__set_errno (EBADF); \ + __fd__ = -1; \ + } \ + ENDTRY \ + if (__fd__ >= cma__g_mx_file) \ + cma__bugcheck ("cma__ts_open: fd is too large"); \ + return __fd__; \ + } +/* + * This macro is used for all "open"-type functions which return a pair of file + * desciptors by reference parameter. + */ +#define cma__ts_open2(func,fdpair,arglist,post_process) { \ + int __res__; \ + TRY { \ + cma__int_init (); \ + cma__int_lock (cma__g_io_data_mutex); \ + __res__ = func arglist; \ + cma__int_unlock (cma__g_io_data_mutex); \ + if (__res__ >= 0 && fdpair[0] < cma__g_mx_file \ + && fdpair[1] < cma__g_mx_file) \ + post_process; \ + } \ + CATCH_ALL \ + { \ + cma__set_errno (EBADF); \ + __res__ = -1; \ + } \ + ENDTRY \ + if ((fdpair[0] >= cma__g_mx_file) || (fdpair[1] >= cma__g_mx_file)) \ + cma__bugcheck ("cma__ts_open2: one of fd's is too large"); \ + return __res__; \ + } + +/* + * INTERNAL INTERFACES + */ +extern void cma__close_general (int); + +extern void +cma__init_thread_io (void); + +extern cma_t_boolean cma__io_available (cma__t_io_type,int,struct timeval *); + +extern void cma__io_epilog (cma__t_io_type,int); + +extern void cma__io_prolog (cma__t_io_type,int); + +extern void cma__io_wait (cma__t_io_type,int); + +extern void cma__open_general (int); + +extern void cma__reinit_thread_io (int); + +extern void cma__set_nonblocking (int); + +extern void cma__set_user_nonblock_flags (int,int); + +extern cma_t_boolean +cma__is_open (int fd); + + +#endif + + diff --git a/gdb/osf-share/cma_attr.h b/gdb/osf-share/cma_attr.h new file mode 100644 index 0000000000..389fd6fd20 --- /dev/null +++ b/gdb/osf-share/cma_attr.h @@ -0,0 +1,341 @@ +/* + * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC. + * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY + * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION + * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems + * To anyone who acknowledges that this file is provided "AS IS" without + * any express or implied warranty: permission to use, copy, modify, and + * distribute this file for any purpose is hereby granted without fee, + * provided that the above copyright notices and this notice appears in + * all source code copies, and that none of the names listed above be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. None of these organizations + * makes any representations about the suitability of this software for + * any purpose. + */ +/* + * Header file for attributes object + */ + +#ifndef CMA_ATTR +#define CMA_ATTR + +/* + * INCLUDE FILES + */ + +#include <cma_defs.h> +#include <cma_queue.h> +#ifdef __hpux +# include <sys/param.h> +#endif +#if _CMA_UNIX_TYPE == _CMA__SVR4 +#include <sys/unistd.h> +#endif +/* + * CONSTANTS AND MACROS + */ + + +/* + * FUNCTIONAL DESCRIPTION: + * + * cma__int_attr_get_priority - Performs the work of cma_attr_get_priority + * + * FORMAL PARAMETERS: + * + * cma_t_attr *_att_ - Attribute object to get from + * cma_t_priority *_setting_ - Current setting + * + * IMPLICIT INPUTS: + * + * none + * + * IMPLICIT OUTPUTS: + * + * priority + * + * FUNCTION VALUE: + * + * none + * + * SIDE EFFECTS: + * + * none + */ +#define cma__int_attr_get_priority(_att_,_setting_) { \ + cma__t_int_attr *_int_att_; \ + (_int_att_) = cma__validate_default_attr (_att_); \ + cma__int_lock ((_int_att_)->mutex); \ + (*(_setting_)) = (_int_att_)->priority; \ + cma__int_unlock ((_int_att_)->mutex); \ + } + + +/* + * FUNCTIONAL DESCRIPTION: + * + * cma__int_attr_get_sched - Performs work of cma_attr_get_sched + * + * FORMAL PARAMETERS: + * + * cma_t_attr *_att_ _ Attributes object used + * cma_t_sched_policy *_setting_ - Current setting + * + * IMPLICIT INPUTS: + * + * none + * + * IMPLICIT OUTPUTS: + * + * scheduling policy + * + * FUNCTION VALUE: + * + * none + * + * SIDE EFFECTS: + * + * none + */ +#define cma__int_attr_get_sched(_att_,_setting_) { \ + cma__t_int_attr *_int_att_; \ + (_int_att_) = cma__validate_default_attr (_att_); \ + cma__int_lock ((_int_att_)->mutex); \ + (*(_setting_)) = (_int_att_)->policy; \ + cma__int_unlock ((_int_att_)->mutex); \ + } + + +/* + * FUNCTIONAL DESCRIPTION: + * + * cma__int_attr_get_inherit_sched - Performs work of + * cma_attr_get_inherit_sched + * + * FORMAL PARAMETERS: + * + * cma_t_attr *_att_ - Attributes object to use + * cma_t_sched_inherit *_setting_ - Current setting + * + * IMPLICIT INPUTS: + * + * none + * + * IMPLICIT OUTPUTS: + * + * Inheritable scheduling policy + * + * FUNCTION VALUE: + * + * none + * + * SIDE EFFECTS: + * + * none + */ +#define cma__int_attr_get_inherit_sched(_att_,_setting_) { \ + cma__t_int_attr *_int_att_; \ + (_int_att_) = cma__validate_default_attr (_att_); \ + cma__int_lock ((_int_att_)->mutex); \ + (*(_setting_)) \ + = ((_int_att_)->inherit_sched ? cma_c_sched_inherit : cma_c_sched_use_default); \ + cma__int_unlock ((_int_att_)->mutex); \ + } + +/* + * FUNCTIONAL DESCRIPTION: + * + * cma__int_attr_set_stacksize - Performs work for cma_attr_set_stacksize + * + * FORMAL PARAMETERS: + * + * cma_t_attr *_att_ - Attributes object to use + * cma_t_natural _setting_ - Setting + * + * IMPLICIT INPUTS: + * + * none + * + * IMPLICIT OUTPUTS: + * + * none + * + * FUNCTION VALUE: + * + * none + * + * SIDE EFFECTS: + * + * Change attribute objects stack size setting + */ +#define cma__int_attr_set_stacksize(_att_,_setting_) { \ + cma__t_int_attr *_int_att_; \ + if ((_setting_) <= 0) \ + cma__error (cma_s_badparam); \ + _int_att_ = cma__validate_attr (_att_); \ + cma__int_lock ((_int_att_)->mutex); \ + _int_att_->stack_size = cma__roundup_chunksize(_setting_); \ + cma__free_cache (_int_att_, cma__c_obj_tcb); \ + _int_att_->cache[cma__c_obj_tcb].revision++; \ + _int_att_->cache[cma__c_obj_stack].revision++; \ + cma__int_unlock (_int_att_->mutex); \ + } + +/* + * FUNCTIONAL DESCRIPTION: + * + * cma__int_attr_get_stacksize - Performs work of cma_attr_get_stacksize + * + * FORMAL PARAMETERS: + * + * cma_t_attr *_att_ - Attributes object to use + * cma_t_natural *_setting_ - Current setting + * + * IMPLICIT INPUTS: + * + * none + * + * IMPLICIT OUTPUTS: + * + * Attribute objects stack size setting + * + * FUNCTION VALUE: + * + * none + * + * SIDE EFFECTS: + * + * none + */ +#define cma__int_attr_get_stacksize(_att_,_setting_) { \ + cma__t_int_attr *_int_att_; \ + (_int_att_) = cma__validate_default_attr (_att_); \ + cma__int_lock ((_int_att_)->mutex); \ + (*(_setting_)) = (_int_att_)->stack_size; \ + cma__int_unlock ((_int_att_)->mutex); \ + } + + +/* + * FUNCTIONAL DESCRIPTION: + * + * cma__int_attr_set_guardsize - Performs work for cma_attr_set_guardsize + * + * FORMAL PARAMETERS: + * + * cma_t_attr *_att_ - Attributes object to use + * cma_t_natural _setting_ - Setting + * + * IMPLICIT INPUTS: + * + * none + * + * IMPLICIT OUTPUTS: + * + * none + * + * FUNCTION VALUE: + * + * none + * + * SIDE EFFECTS: + * + * Change attribute objects guard size setting + */ +#define cma__int_attr_set_guardsize(_att_,_setting_) { \ + cma__t_int_attr *_int_att_; \ + _int_att_ = cma__validate_attr (_att_); \ + cma__int_lock ((_int_att_)->mutex); \ + _int_att_->guard_size = cma__roundup_chunksize(_setting_); \ + cma__free_cache (_int_att_, cma__c_obj_tcb); \ + _int_att_->cache[cma__c_obj_tcb].revision++; \ + _int_att_->cache[cma__c_obj_stack].revision++; \ + cma__int_unlock (_int_att_->mutex); \ + } + +/* + * FUNCTIONAL DESCRIPTION: + * + * cma__int_attr_get_guardsize - Performs work of cma_attr_get_guardsize + * + * FORMAL PARAMETERS: + * + * cma_t_attr *_att_ - Attributes object to use + * cma_t_natural *_setting_ - Current setting + * + * IMPLICIT INPUTS: + * + * none + * + * IMPLICIT OUTPUTS: + * + * Attribute objects guard size setting + * + * FUNCTION VALUE: + * + * none + * + * SIDE EFFECTS: + * + * none + */ +#define cma__int_attr_get_guardsize(_att_,_setting_) { \ + cma__t_int_attr *_int_att_; \ + (_int_att_) = cma__validate_default_attr (_att_); \ + cma__int_lock ((_int_att_)->mutex); \ + (*(_setting_)) = (_int_att_)->guard_size; \ + cma__int_unlock ((_int_att_)->mutex); \ + } + +/* + * TYPEDEFS + */ +#ifndef __STDC__ +struct CMA__T_INT_MUTEX; /* Avoid circular dependency */ +#endif + +typedef struct CMA__T_CACHE { + cma_t_natural revision; /* Revisions */ + cma_t_natural count; + cma__t_queue queue; /* Cache headers */ + } cma__t_cache; + +typedef struct CMA__T_INT_ATTR { + cma__t_object header; /* Common header */ + struct CMA__T_INT_ATTR *attributes; /* Point to controlling attr */ + struct CMA__T_INT_MUTEX *mutex; /* Serialize access to object */ + cma_t_priority priority; /* Priority of new thread */ + cma_t_sched_policy policy; /* Sched policy of thread */ + cma_t_boolean inherit_sched; /* Is scheduling inherited? */ + cma_t_natural stack_size; /* Size of stack (bytes) */ + cma_t_natural guard_size; /* Size of guard (bytes) */ + cma_t_mutex_kind mutex_kind; /* Mutex kind */ + cma__t_cache cache[cma__c_obj_num]; /* Cache information */ + cma_t_boolean delete_pending; /* attr. obj. is deleted */ + cma_t_natural refcnt; /* Number of objects using attr. obj */ + } cma__t_int_attr; + +/* + * GLOBAL DATA + */ + +extern cma__t_int_attr cma__g_def_attr; + +/* + * INTERNAL INTERFACES + */ + +extern void cma__destroy_attributes (cma__t_int_attr *); + +extern void cma__free_attributes (cma__t_int_attr *); + +extern void cma__free_cache (cma__t_int_attr *,cma_t_natural ); + +extern cma__t_int_attr *cma__get_attributes (cma__t_int_attr *); + +extern void cma__init_attr (void); + +extern void cma__reinit_attr (cma_t_integer); + +#endif diff --git a/gdb/osf-share/cma_deb_core.h b/gdb/osf-share/cma_deb_core.h new file mode 100644 index 0000000000..f0a9c34167 --- /dev/null +++ b/gdb/osf-share/cma_deb_core.h @@ -0,0 +1,164 @@ +/* + * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC. + * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY + * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION + * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems + * To anyone who acknowledges that this file is provided "AS IS" without + * any express or implied warranty: permission to use, copy, modify, and + * distribute this file for any purpose is hereby granted without fee, + * provided that the above copyright notices and this notice appears in + * all source code copies, and that none of the names listed above be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. None of these organizations + * makes any representations about the suitability of this software for + * any purpose. + */ +/* + * This file defines the internal interface to the core of CMA + * debugging services. (The client interface to debugging services + * is provided by cma_debug_client.h). + */ + +#ifndef CMA_DEB_CORE +#define CMA_DEB_CORE + +/* + * INCLUDE FILES + */ +#include <cma.h> +#include <cma_mutex.h> +#include <cma_queue.h> +#include <cma_tcb_defs.h> +#include <cma_util.h> + +/* + * CONSTANTS AND MACROS + */ + + +/* + * TYPEDEFS + */ + +/*FIX-ME* Need to use sizes that are platform specific */ +typedef long int cma___t_debug_ctx[17]; + +/* + * Type defing the format of known object lists + */ +typedef struct CMA__T_KNOWN_OBJECT { + cma__t_queue queue; /* Queue header for known objects */ + cma__t_int_mutex *mutex; /* Mutex to control access to queue */ + } cma__t_known_object; + + +/* + * Type defining the registration for one debug client (e.g. Ada) + */ +typedef struct CMA__T_DEB_REGISTRY { + cma_t_address entry; /* Client's debug entry point */ + cma_t_key key; /* Client's context key */ + cma_t_integer fac; /* Client's debug facility number */ + cma_t_boolean has_prolog; /* Client's TCBs have std prolog */ + } cma__t_deb_registry; + +#define cma__c_deb_max_clients 10 + +/* + * Type defining the global debugging state for all threads. + */ +typedef struct CMA__T_DEBUG_STATE { + /* + * The following flag is set if changes were made while in the + * debugger that may make the ready lists inconsistent. For + * example, if a thread priority is changed in the debugger, the + * thread is not moved between queues. Making things consistent + * is deferred to when the dispatcher is next invoked -- which we + * try to make very soon. + */ + cma_t_boolean is_inconsistency; /* Ready lists are inconsistent */ + + + cma_t_boolean events_enabled; /* Set if _any_ event is enabled */ + cma_t_boolean flags[cma__c_debevt__dim]; + /* Which events are enabled */ + cma__t_int_tcb *next_to_run; /* TCB of thread to run next */ + + cma__t_int_mutex *mutex; /* Mutex for registering clients */ + cma_t_integer client_count; /* Count of debug clients */ + cma__t_deb_registry clients[cma__c_deb_max_clients+1]; + /* Array of current debug clients */ + } cma__t_debug_state; + + +/* + * Routine that will symbolize and address and print it. + */ +typedef void (*cma__t_print_symbol) (cma_t_address); + + +/* + * GLOBAL DATA + */ + +/* + * Variable holding the global debugging state + * + * (This is primarily written by the debugger interface and read + * by the thread dispatcher). + */ +extern cma__t_debug_state cma__g_debug_state; + +/* + * Known object queues + */ +extern cma__t_known_object cma__g_known_atts; +extern cma__t_known_object cma__g_known_cvs; +extern cma__t_known_object cma__g_known_mutexes; +extern cma__t_known_object cma__g_known_threads; + +/* + * INTERNAL INTERFACES + */ + +/* Get information while in debugger context */ +extern void cma__deb_get + (cma__t_int_tcb *,cma_t_debug_get,cma_t_address,cma_t_integer,cma_t_integer); + +/* Set information while in debugger context */ +extern void cma__deb_set (cma__t_int_tcb *,cma_t_debug_set,cma_t_address,cma_t_integer); + +extern void cma__init_debug (void); + +extern void cma__reinit_debug (cma_t_integer); + +extern void cma__deb_anytcb_to_tcb (cma_t_tcb_header *,cma__t_int_tcb **); + +extern void cma__deb_fac_to_client (cma_t_integer,cma_t_key *); + +extern void cma__deb_get_client_info (cma_t_key,cma_t_address *,cma_t_boolean *); + +extern void cma__deb_get_context (cma__t_int_tcb *,cma_t_key,cma_t_address *); + +extern cma__t_int_tcb *cma__deb_get_self_tcb (void); + +extern void cma__deb_get_time_slice (cma_t_interval *); + +extern cma__t_int_tcb *cma__deb_next_tcb + (cma__t_int_tcb *,cma_t_integer *,cma_t_integer *,cma_t_boolean *); + +extern cma_t_boolean cma__deb_set_alert (cma__t_int_tcb *); + +extern void cma__deb_set_next_thread (cma__t_int_tcb *); + +extern void cma__deb_set_force_dispatch (cma_t_address ); + +extern void cma__deb_set_time_slice (cma_t_interval); + +extern void cma__deb_show_thread + (cma__t_int_tcb *,cma_t_boolean,cma_t_boolean,cma___t_debug_ctx,cma__t_eol_routine, + cma__t_eol_routine,cma__t_print_symbol); + +extern void +cma__deb_show_stats (cma__t_int_tcb *,cma_t_boolean,cma_t_boolean,cma__t_eol_routine,cma__t_eol_routine,cma__t_print_symbol); +#endif diff --git a/gdb/osf-share/cma_debug_client.h b/gdb/osf-share/cma_debug_client.h new file mode 100644 index 0000000000..adb0909ad7 --- /dev/null +++ b/gdb/osf-share/cma_debug_client.h @@ -0,0 +1,195 @@ +/* + * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC. + * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY + * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION + * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems + * To anyone who acknowledges that this file is provided "AS IS" without + * any express or implied warranty: permission to use, copy, modify, and + * distribute this file for any purpose is hereby granted without fee, + * provided that the above copyright notices and this notice appears in + * all source code copies, and that none of the names listed above be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. None of these organizations + * makes any representations about the suitability of this software for + * any purpose. + */ +/* + * Header file providing access to CMA clients that implement + * language run-times to the CMA debugger capabilities. + * + * NOTE: the clients that are able to use this interface is + * very limited because clients needing task debugging must have + * support in the system debugger as well as here (at present). + * The following are the only legitimate clients of this interface: + * ADA runtime, C++ tasking library, and CMA. + * + *FIX-ME* We shall endeavor to extend these capabilities so that the + * all-platform CMA debugger CMA_DEBUG and any client can layer + * on thread debugging. But that is still an open design problem. + * The design here does not preclude that extension (for example, + * the identity of the debug-client is indicated in an "open" + * manner by using the CMA context key as the identifier. + */ + +#ifndef CMA_DEBUG_CLIENT +#define CMA_DEBUG_CLIENT + +/* + * INCLUDE FILES + */ +#include <cma.h> + +/* + * CONSTANTS AND MACROS + */ + +/* + * TYPEDEFS + */ + +/* + * Type describing constants for a valid TCB sentinel. + * Exactly one value is valid, but we provide a symbolic name for + * at least one invalid sentinel as a convenience. + */ +typedef enum CMA_T_TCB_SENTINEL { + cma_c_tcb_sentinel_nogood = 0, /* Invalid sentinel constant */ + cma_c_tcb_sentinel = 0x0ACEFACE /* Valid TCB sentinel */ + } cma_t_tcb_sentinel; + +/* + * Type describing pad fields needed to align the "standard prolog" + * to the right byte at the front of each TCB. These fields are + * free to be put to any use by the client. + * + * This is 32 bytes long and is fixed at this size for all clients + * and CMA, for all time. + */ +typedef struct CMA_T_TCB_PRIVATE { + cma_t_integer pad1; + cma_t_integer pad2; + cma_t_integer pad3; + cma_t_integer pad4; + cma_t_integer pad5; + cma_t_integer pad6; + cma_t_integer pad7; + cma_t_integer pad8; + } cma_t_tcb_private; + +/* + * Type describing the "standard prolog" that clients should use + * within their task control blocks. We assume that the client will + * store their "task control block" as a per-thread context under + * the context key specified here. + */ +typedef struct CMA_T_TCB_PROLOG { + cma_t_tcb_sentinel sentinel; /* Validity sentinel */ + cma_t_thread client_thread; /* Thread corresonding to task */ + cma_t_key client_key; /* Context key this is stored under */ + cma_t_address reserved1; /* Must be zero, reserved to CMA */ + } cma_t_tcb_prolog; + +/* + * Type defining the layout of all TCBs and TASKS. This format + * ensures that tasks will be self-identifying to the debugger. + * this layout must never change as the CMA DEBUG Clients cannot + * be changed after CMA ships. + */ +typedef struct CMA_T_TCB_HEADER { + cma_t_tcb_private IGNORED; /* TCB fields private to the client */ + cma_t_tcb_prolog prolog; /* The standard prolog goes here */ + } cma_t_tcb_header; + + +/* + * Type describing the kinds of information that a CMA debug + * client can GET about a thread. + */ +typedef enum CMA_T_DEBUG_GET { + /* + * All of the following items use a buffer whose size is + * four bytes. (That is four must be passed as the buffer_size + * parameter to cma_debug_get.) + */ + cma_c_debget_guardsize = 1, /* Current guard size (bytes) */ + cma_c_debget_is_held = 2, /* Is it on hold? */ + cma_c_debget_is_initial = 3, /* Is it the initial thread? */ + cma_c_debget_number = 4, /* Thread's number */ + cma_c_debget_stack_ptr = 5, /* Current stack pointer */ + cma_c_debget_stack_base = 6, /* Stack base address */ + cma_c_debget_stack_top = 7, /* Stack top address */ + cma_c_debget_sched_state = 8, /* Scheduler state + * 0 - run + * 1 - ready + * 2 - blocked + * 3 - terminated + */ + cma_c_debget_reserve_size = 9, /* Size of stack reserve (bytes) */ + cma_c_debget_base_prio = 10, /* Base priority */ + cma_c_debget_priority = 11, /* Current priority */ + cma_c_debget_regs = 12, /* Register set (and proc. state) */ + cma_c_debget_alt_pending = 13, /* Alert is pending */ + cma_c_debget_alt_a_enable = 14, /* Asynch alert delivery enabled */ + cma_c_debget_alt_g_enable = 15, /* General alert delivery enabled */ + cma_c_debget_substate = 16, /* Substate (or wait state) */ + cma_c_debget_object_addr = 17, /* Address of thread object */ + cma_c_debget_thkind = 18, /* Kind of thread */ + cma_c_debget_detached = 19, /* Thread is detached */ + cma_c_debget_tcb_size = 20, /* TCB size */ + cma_c_debget_start_pc = 21, /* Start address */ + cma_c_debget_next_pc = 22, /* Next instruction */ + cma_c_debget_policy = 23, /* Sched policy */ + cma_c_debget_stack_yellow = 24, /* Addr of start of guard area */ + cma_c_debget_stack_default = 25 /* True if on default stack */ + + } cma_t_debug_get; + +/* + * Type describing the kinds of information that a CMA debug + * client can SET (or change) about a thread using cma_debug_set. + */ +typedef enum CMA_T_DEBUG_SET { + /* + * All of the following items use a buffer whose size is + * four bytes. (That is four must be passed as the buffer_size + * parameter to cma_debug_set.) + */ + cma_c_debset_priority = 1, /* Set the priority */ + cma_c_debset_policy = 2, /* Set the sched policy */ + cma_c_debset_hold = 3, /* Put thread on hold */ + cma_c_debset_regs = 4 /* Set the regs and proc. state */ + + } cma_t_debug_set; + + +/* + * GLOBAL DATA + * + * none + */ + +/* + * EXTERNAL INTERFACES + */ + +/* + * Routine to register with the CMA debug dispatcher. + */ +extern void cma_debug_register (cma_t_address,cma_t_key,cma_t_integer,cma_t_boolean); + +/* + * Routine to get get thread state needed by the CMA debug client. + */ +extern void cma_debug_get (cma_t_thread *,cma_t_debug_get,cma_t_address,cma_t_integer); + +/* + * Get thread context given an sp and a key + */ +extern void cma_debug_get_sp_context (cma_t_address,cma_t_key,cma_t_address *); + +/* + * Routine to set thread state as needed by the CMA debug client. + */ +extern void cma_debug_set (cma_t_thread *,cma_t_debug_set,cma_t_address,cma_t_integer); + +#endif diff --git a/gdb/osf-share/cma_errors.h b/gdb/osf-share/cma_errors.h new file mode 100644 index 0000000000..8ac1795745 --- /dev/null +++ b/gdb/osf-share/cma_errors.h @@ -0,0 +1,55 @@ +/* + * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC. + * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY + * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION + * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems + * To anyone who acknowledges that this file is provided "AS IS" without + * any express or implied warranty: permission to use, copy, modify, and + * distribute this file for any purpose is hereby granted without fee, + * provided that the above copyright notices and this notice appears in + * all source code copies, and that none of the names listed above be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. None of these organizations + * makes any representations about the suitability of this software for + * any purpose. + */ +/* + * This module is the interface between CMA services and + * the platform-specific error reporting mechanism. + */ + +#ifndef CMA_ERRORS +#define CMA_ERRORS + +/* + * INCLUDE FILES + */ + +/* + * CONSTANTS AND MACROS + */ + +/* + * TYPEDEFS + */ + +/* + * GLOBAL DATA + */ + +/* + * INTERNAL INTERFACES + */ + +/* + * The cma__bugcheck function will print information to stderr (or sys$error + * on VMS), and more extensive information to the file cma_dump.log in the + * current working directory. + */ +extern void cma__bugcheck (char *,...); + +extern void cma__error (int); + +extern void cma__unimplemented (void); + +#endif diff --git a/gdb/osf-share/cma_handle.h b/gdb/osf-share/cma_handle.h new file mode 100644 index 0000000000..e63de018a0 --- /dev/null +++ b/gdb/osf-share/cma_handle.h @@ -0,0 +1,182 @@ +/* + * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC. + * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY + * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION + * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems + * To anyone who acknowledges that this file is provided "AS IS" without + * any express or implied warranty: permission to use, copy, modify, and + * distribute this file for any purpose is hereby granted without fee, + * provided that the above copyright notices and this notice appears in + * all source code copies, and that none of the names listed above be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. None of these organizations + * makes any representations about the suitability of this software for + * any purpose. + */ +/* + * Header file for handles + */ + +#ifndef CMA_HANDLE +#define CMA_HANDLE + +/* + * INCLUDE FILES + */ + +#include <cma_defs.h> +#include <cma_attr.h> + +/* + * CONSTANTS AND MACROS + */ + +#define cma__validate_attr(handle) \ + ((cma__t_int_attr *)cma__validate_handle ( \ + (cma_t_handle *)(handle), \ + cma__c_obj_attr)) + +#define cma__validate_cv(handle) \ + ((cma__t_int_cv *)cma__validate_handle ( \ + (cma_t_handle *)(handle), \ + cma__c_obj_cv)) + +#define cma__validate_mutex(handle) \ + ((cma__t_int_mutex *)cma__validate_handle ( \ + (cma_t_handle *)(handle), \ + cma__c_obj_mutex)) + +#define cma__validate_tcb(handle) \ + ((cma__t_int_tcb *)cma__validate_handle ( \ + (cma_t_handle *)(handle), \ + cma__c_obj_tcb)) + +#define cma__validate_stack(handle) \ + ((cma__t_int_stack *)cma__validate_handle ( \ + (cma_t_handle *)(handle), \ + cma__c_obj_stack)) + +#define cma__validate_null_attr(handle) \ + ((cma__t_int_attr *)cma__validate_handle_null ( \ + (cma_t_handle *)(handle), \ + cma__c_obj_attr)) + +#define cma__validate_null_cv(handle) \ + ((cma__t_int_cv *)cma__validate_handle_null ( \ + (cma_t_handle *)(handle), \ + cma__c_obj_cv)) + +#define cma__validate_null_mutex(handle) \ + ((cma__t_int_mutex *)cma__validate_handle_null ( \ + (cma_t_handle *)(handle), \ + cma__c_obj_mutex)) + +#define cma__validate_null_tcb(handle) \ + ((cma__t_int_tcb *)cma__validate_handle_null ( \ + (cma_t_handle *)(handle), \ + cma__c_obj_tcb)) + +#define cma__validate_null_stack(handle) \ + ((cma__t_int_stack *)cma__validate_handle_null ( \ + (cma_t_handle *)(handle), \ + cma__c_obj_stack)) + +#define cma__val_attr_stat(handle,obj) \ + cma__val_hand_stat ( \ + (cma_t_handle *)(handle), \ + cma__c_obj_attr, \ + (cma__t_object **)obj) + +#define cma__val_cv_stat(handle,obj) \ + cma__val_hand_stat ( \ + (cma_t_handle *)(handle), \ + cma__c_obj_cv, \ + (cma__t_object **)obj) + +#define cma__val_mutex_stat(handle,obj) \ + cma__val_hand_stat ( \ + (cma_t_handle *)(handle), \ + cma__c_obj_mutex, \ + (cma__t_object **)obj) + +#define cma__val_tcb_stat(handle) \ + cma__val_hand_stat ( \ + (cma_t_handle *)(handle), \ + cma__c_obj_tcb, \ + (cma__t_object **)obj) + +#define cma__val_stack_stat(handle,obj) \ + cma__val_hand_stat ( \ + (cma_t_handle *)(handle), \ + cma__c_obj_stack, \ + (cma__t_object **)obj) + +#define cma__val_nullattr_stat(handle,obj) \ + cma__val_handnull_stat ( \ + (cma_t_handle *)(handle), \ + cma__c_obj_attr, \ + (cma__t_object **)obj) + +#define cma__val_nullcv_stat(handle,obj) \ + cma__val_handnull_stat ( \ + (cma_t_handle *)(handle), \ + cma__c_obj_cv, \ + (cma__t_object **)obj) + +#define cma__val_nullmutex_stat(handle,obj) \ + cma__val_handnull_stat ( \ + (cma_t_handle *)(handle), \ + cma__c_obj_mutex, \ + (cma__t_object **)obj) + +#define cma__val_nulltcb_stat(handle,obj) \ + cma__val_handnull_stat ( \ + (cma_t_handle *)(handle), \ + cma__c_obj_tcb, \ + (cma__t_object **)obj) + +#define cma__val_nullstack_stat(handle) \ + cma__val_handnull_stat ( \ + (cma_t_handle *)(handle), \ + cma__c_obj_stack, \ + (cma__t_object **)obj) + +/* + * TYPEDEFS + */ + +/* + * Internal format of a handle (to the outside world it's an array of two + * addresses, but we know better). + */ +typedef struct CMA__T_INT_HANDLE { + cma__t_object *pointer; /* Address of internal structure */ + cma__t_short sequence; /* Sequence number of object */ + cma__t_short type; /* Type code of object */ + } cma__t_int_handle; + +/* + * GLOBAL DATA + */ + +/* + * INTERNAL INTERFACES + */ + +extern void cma__clear_handle (cma_t_handle *); + +extern void cma__object_to_handle (cma__t_object *,cma_t_handle *); + +extern cma__t_int_attr * cma__validate_default_attr (cma_t_handle *); + +extern cma_t_status cma__val_defattr_stat (cma_t_handle *,cma__t_int_attr **); + +extern cma__t_object * cma__validate_handle (cma_t_handle *,cma_t_natural ); + +extern cma_t_status cma__val_hand_stat (cma_t_handle *,cma_t_natural,cma__t_object **); + +extern cma__t_object *cma__validate_handle_null (cma_t_handle *,cma_t_natural); + +extern cma_t_status cma__val_handnull_stat (cma_t_handle *,cma_t_natural,cma__t_object **); + +#endif diff --git a/gdb/osf-share/cma_init.h b/gdb/osf-share/cma_init.h new file mode 100644 index 0000000000..7309736c19 --- /dev/null +++ b/gdb/osf-share/cma_init.h @@ -0,0 +1,114 @@ +/* + * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC. + * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY + * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION + * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems + * To anyone who acknowledges that this file is provided "AS IS" without + * any express or implied warranty: permission to use, copy, modify, and + * distribute this file for any purpose is hereby granted without fee, + * provided that the above copyright notices and this notice appears in + * all source code copies, and that none of the names listed above be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. None of these organizations + * makes any representations about the suitability of this software for + * any purpose. + */ +/* + * Header file for CMA initialization + */ + +#ifndef CMA_INIT +#define CMA_INIT + +/* + * INCLUDE FILES + */ +#include <dce/cma_host.h> +#include <cma_errors.h> + +/* + * CONSTANTS AND MACROS + */ + +#define cma__c_env_maxattr 0 +#define cma__c_env_minattr 1 +#define cma__c_env_maxcond 2 +#define cma__c_env_mincond 3 +#define cma__c_env_maxmutex 4 +#define cma__c_env_minmutex 5 +#define cma__c_env_maxthread 6 +#define cma__c_env_minthread 7 +#define cma__c_env_maxcluster 8 +#define cma__c_env_mincluster 9 +#define cma__c_env_maxvp 10 +#define cma__c_env_multiplex 11 +#define cma__c_env_trace 12 +#define cma__c_env_trace_file 13 + +#define cma__c_env_count 13 + + +/* + * cma__int_init + * + * Initialize the main body of CMA exactly once. + * + * We raise an exception if, for some odd reason, there are already threads + * in the environment (e.g. kernel threads), and one of them is trying to + * initialize CMA before the first thread got all the way through the actual + * initialization. This code maintains the invariants: "after successfully + * calling CMA_INIT, you can call any CMA function", and "CMA is actually + * initialized at most once". + */ +/*#ifndef _HP_LIBC_R */ + +#if defined _HP_LIBC_R ||(defined(SNI_SVR4) && !defined(CMA_INIT_NEEDED)) +# define cma__int_init() +#else +# define cma__int_init() { \ + if (!cma__tac_isset(&cma__g_init_started)) { \ + if (!cma__test_and_set (&cma__g_init_started)) { \ + cma__init_static (); \ + cma__test_and_set (&cma__g_init_done); \ + } \ + else if (!cma__tac_isset (&cma__g_init_done)) { \ + cma__error (cma_s_inialrpro); \ + }}} +#endif + +/* + * TYPEDEFS + */ + +typedef enum CMA__T_ENV_TYPE { + cma__c_env_type_int, + cma__c_env_type_file + } cma__t_env_type; + +typedef struct CMA__T_ENV { + char *name; /* Name of environment variable */ + cma__t_env_type type; /* Type of variable */ + cma_t_integer value; /* Numeric value of the variable */ + } cma__t_env; + +/* + * GLOBAL DATA + */ + +extern cma__t_env cma__g_env[cma__c_env_count]; +extern cma__t_atomic_bit cma__g_init_started; +extern cma__t_atomic_bit cma__g_init_done; +extern char *cma__g_version; + +/* + * INTERNAL INTERFACES + */ + +extern void +cma__init_static (void); /* Initialize static data */ + +#if _CMA_OS_ != _CMA__VMS +extern void cma__init_atfork (void); +#endif + +#endif diff --git a/gdb/osf-share/cma_list.h b/gdb/osf-share/cma_list.h new file mode 100644 index 0000000000..463fa49870 --- /dev/null +++ b/gdb/osf-share/cma_list.h @@ -0,0 +1,84 @@ +/* + * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC. + * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY + * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION + * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems + * To anyone who acknowledges that this file is provided "AS IS" without + * any express or implied warranty: permission to use, copy, modify, and + * distribute this file for any purpose is hereby granted without fee, + * provided that the above copyright notices and this notice appears in + * all source code copies, and that none of the names listed above be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. None of these organizations + * makes any representations about the suitability of this software for + * any purpose. + */ +/* + * Header file for generic list functions operating on singly linked + * null-terminated lists. Items may not be REMOVED from the list! The + * intent is that the list can be traversed (for read-only operations) + * without locking, since insertion is "safe" (though not truely + * atomic). THIS ASSUMES THAT THE HARDWARE MAKES WRITES VISIBLE TO READS + * IN THE ORDER IN WHICH THEY OCCURRED! WITHOUT SUCH READ/WRITE + * ORDERING, IT MAY BE NECESSARY TO INSERT "BARRIERS" TO PRODUCE THE + * REQUIRED VISIBILITY! + */ + +#ifndef CMA_LIST +#define CMA_LIST + +/* + * INCLUDE FILES + */ + +#include <cma.h> + +/* + * CONSTANTS AND MACROS + */ + +#define cma__c_null_list ((cma__t_list *)cma_c_null_ptr) + +/* + * Test whether a list is empty. Return cma_c_true if so, else + * cma_c_false. + */ +#define cma__list_empty(head) ((head)->link == cma__c_null_list) + +/* + * Initialize a queue header to empty. + */ +#define cma__list_init(head) (void)((head)->link = cma__c_null_list) + +/* + * Insert an element in a list following the specified item (or at the + * beginning of the list if "list" is the list head). NOTE: insertion + * operations should be interlocked by the caller! + */ +#define cma__list_insert(element,list) (void)( \ + (element)->link = (list)->link, \ + (list)->link = (element)) + +/* + * Return the next item in a list (or the first, if the address is of the + * list header) + */ +#define cma__list_next(element) ((element)->link) + +/* + * TYPEDEFS + */ + +typedef struct CMA__T_LIST { + struct CMA__T_LIST *link; /* Forward link */ + } cma__t_list; + +/* + * GLOBAL DATA + */ + +/* + * INTERNAL INTERFACES + */ + +#endif diff --git a/gdb/osf-share/cma_mutex.h b/gdb/osf-share/cma_mutex.h new file mode 100644 index 0000000000..c178630dc8 --- /dev/null +++ b/gdb/osf-share/cma_mutex.h @@ -0,0 +1,230 @@ +/* + * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC. + * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY + * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION + * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems + * To anyone who acknowledges that this file is provided "AS IS" without + * any express or implied warranty: permission to use, copy, modify, and + * distribute this file for any purpose is hereby granted without fee, + * provided that the above copyright notices and this notice appears in + * all source code copies, and that none of the names listed above be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. None of these organizations + * makes any representations about the suitability of this software for + * any purpose. + */ +/* + * Header file for mutex operations + */ + +#ifndef CMA_MUTEX +#define CMA_MUTEX + +/* + * INCLUDE FILES + */ + +#include <cma.h> +#include <cma_attr.h> +#include <cma_defs.h> +#include <cma_semaphore_defs.h> +#include <cma_sequence.h> +#include <cma_tcb_defs.h> +#include <cma_stack.h> + +/* + * CONSTANTS AND MACROS + */ + +/* + * TYPEDEFS + */ + +typedef struct CMA__T_INT_MUTEX { + cma__t_object header; /* Common header (sequence, type) */ + cma__t_int_attr *attributes; /* Back link */ + cma__t_int_tcb *owner; /* Current owner (if any) */ + cma_t_integer nest_count; /* Nesting level for recursive mutex */ + cma__t_atomic_bit *unlock; /* Pointer used for unlock operation */ + cma__t_atomic_bit lock; /* Set if currently locked */ + struct CMA__T_INT_MUTEX *int_lock; /* Internal protection for mutex */ + cma__t_atomic_bit event; /* Clear when unlock requires action */ + cma__t_atomic_bit waiters; /* Clear when threads are waiting */ + cma__t_atomic_bit bitbucket; /* Fake bit to keep friendlies locked */ + cma_t_mutex_kind mutex_kind; /* Kind of mutex */ + cma__t_semaphore semaphore; /* Semaphore for low-level wait */ + } cma__t_int_mutex; + + +/* + * FUNCTIONAL DESCRIPTION: + * + * Lock a mutex (internal) + * + * FORMAL PARAMETERS: + * + * mutex Pointer to mutex object to lock + * + * IMPLICIT INPUTS: + * + * none + * + * IMPLICIT OUTPUTS: + * + * none + * + * FUNCTION VALUE: + * + * none + * + * SIDE EFFECTS: + * + * none + */ +#ifdef NDEBUG +# define cma__int_lock(mutex) { \ + if (cma__test_and_set (&((cma__t_int_mutex *)mutex)->lock)) { \ + cma_t_status res;\ + res = cma__int_mutex_block ((cma__t_int_mutex *)mutex); \ + if (res != cma_s_normal) cma__error (res); \ + } \ + } +#else +# define cma__int_lock(mutex) { \ + cma__t_int_tcb *__ltcb__; \ + __ltcb__ = cma__get_self_tcb (); \ + if (cma__test_and_set (&((cma__t_int_mutex *)mutex)->lock)) { \ + cma_t_status res;\ + res = cma__int_mutex_block ((cma__t_int_mutex *)mutex); \ + if (res != cma_s_normal) cma__error (res); \ + } \ + ((cma__t_int_mutex *)mutex)->owner = __ltcb__; \ + } +#endif + +/* + * FUNCTIONAL DESCRIPTION: + * + * Unlock a mutex (internal) + * + * FORMAL PARAMETERS: + * + * mutex Pointer to mutex object to unlock + * + * IMPLICIT INPUTS: + * + * none + * + * IMPLICIT OUTPUTS: + * + * none + * + * FUNCTION VALUE: + * + * none + * + * SIDE EFFECTS: + * + * none + */ +#ifdef NDEBUG +# define cma__int_unlock(mutex) { \ + cma__unset (((cma__t_int_mutex *)mutex)->unlock); \ + if (!cma__test_and_set (&((cma__t_int_mutex *)mutex)->event)) { \ + cma_t_status res;\ + res = cma__int_mutex_unblock ((cma__t_int_mutex *)mutex); \ + if (res != cma_s_normal) cma__error (res); \ + } \ + } +#else +# define cma__int_unlock(mutex) { \ + cma__t_int_tcb *__utcb__; \ + __utcb__ = cma__get_self_tcb (); \ + if (((cma__t_int_mutex *)mutex)->mutex_kind == cma_c_mutex_fast) { \ + cma__assert_warn ( \ + (__utcb__ == ((cma__t_int_mutex *)mutex)->owner), \ + "attempt to release mutx owned by another thread"); \ + ((cma__t_int_mutex *)mutex)->owner = (cma__t_int_tcb *)cma_c_null_ptr; \ + } \ + cma__unset (((cma__t_int_mutex *)mutex)->unlock); \ + if (!cma__test_and_set (&((cma__t_int_mutex *)mutex)->event)) { \ + cma_t_status res;\ + res = cma__int_mutex_unblock ((cma__t_int_mutex *)mutex); \ + if (res != cma_s_normal) cma__error (res); \ + } \ + } +#endif + +/* + * FUNCTIONAL DESCRIPTION: + * + * cma__int_mutex_delete - Performs work for cma_mutex_delete + * + * FORMAL PARAMETERS: + * + * cma__t_mutex _mutex_ - Mutex to be deleted + * + * IMPLICIT INPUTS: + * + * none + * + * IMPLICIT OUTPUTS: + * + * none + * + * FUNCTION VALUE: + * + * none + * + * SIDE EFFECTS: + * + * none + */ +#define cma__int_mutex_delete(_mutex_) { \ + cma__t_int_mutex *_int_mutex_; \ + _int_mutex_ = cma__validate_null_mutex (_mutex_); \ + if (_int_mutex_ == (cma__t_int_mutex *)cma_c_null_ptr) \ + return; \ + if (cma__int_mutex_locked (_int_mutex_)) \ + cma__error (cma_s_in_use); \ + cma__free_mutex (_int_mutex_); \ + cma__clear_handle (_mutex_); \ + } + + +/* + * GLOBAL DATA + */ + +extern cma__t_sequence cma__g_mutex_seq; +extern cma__t_int_mutex *cma__g_global_lock; + +/* + * INTERNAL INTERFACES + */ + +extern void cma__destroy_mutex (cma__t_int_mutex *); + +extern void cma__free_mutex (cma__t_int_mutex *); + +extern void cma__free_mutex_nolock (cma__t_int_mutex *); + +extern cma__t_int_mutex * cma__get_first_mutex (cma__t_int_attr *); + +extern cma__t_int_mutex * cma__get_mutex (cma__t_int_attr *); + +extern void cma__init_mutex (void); + +extern cma_t_status cma__int_mutex_block (cma__t_int_mutex *); + +extern cma_t_boolean cma__int_mutex_locked (cma__t_int_mutex *); + +extern cma_t_boolean cma__int_try_lock (cma__t_int_mutex *); + +extern cma_t_status cma__int_mutex_unblock (cma__t_int_mutex *); + +extern cma_t_boolean cma__mutex_locked (cma_t_mutex); + +extern void cma__reinit_mutex (cma_t_integer); + +#endif diff --git a/gdb/osf-share/cma_sched.h b/gdb/osf-share/cma_sched.h new file mode 100644 index 0000000000..6eb78743ba --- /dev/null +++ b/gdb/osf-share/cma_sched.h @@ -0,0 +1,279 @@ +/* + * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC. + * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY + * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION + * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems + * To anyone who acknowledges that this file is provided "AS IS" without + * any express or implied warranty: permission to use, copy, modify, and + * distribute this file for any purpose is hereby granted without fee, + * provided that the above copyright notices and this notice appears in + * all source code copies, and that none of the names listed above be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. None of these organizations + * makes any representations about the suitability of this software for + * any purpose. + */ +/* + * Header file for priority scheduling + */ + + +#ifndef CMA_SCHED +#define CMA_SCHED + +/* + * INCLUDE FILES + */ + +/* + * CONSTANTS AND MACROS + */ + +/* + * Scaling factor for integer priority calculations + */ +#define cma__c_prio_scale 8 + +#if _CMA_VENDOR_ == _CMA__APOLLO +/* + * FIX-ME: Apollo cc 6.8 blows contant folded "<<" and ">>" + */ +# define cma__scale_up(exp) ((exp) * 256) +# define cma__scale_dn(exp) ((exp) / 256) +#else +# define cma__scale_up(exp) ((exp) << cma__c_prio_scale) +# define cma__scale_dn(exp) ((exp) >> cma__c_prio_scale) +#endif + + +/* + * Min. num. of ticks between self-adjustments for priority adjusting policies. + */ +#define cma__c_prio_interval 10 + + +/* + * Number of queues in each class of queues + */ +#define cma__c_prio_n_id 1 /* Very-low-priority class threads */ +#define cma__c_prio_n_bg 8 /* Background class threads */ +#define cma__c_prio_n_0 1 /* Very low priority throughput quartile */ +#define cma__c_prio_n_1 2 /* Low priority throughput quartile */ +#define cma__c_prio_n_2 3 /* Medium priority throughput quartile */ +#define cma__c_prio_n_3 4 /* High priority throughput quartile */ +#define cma__c_prio_n_rt 1 /* Real Time priority queues */ + +/* + * Number of queues to skip (offset) to get to the queues in this section of LA + */ +#define cma__c_prio_o_id 0 +#define cma__c_prio_o_bg cma__c_prio_o_id + cma__c_prio_n_id +#define cma__c_prio_o_0 cma__c_prio_o_bg + cma__c_prio_n_bg +#define cma__c_prio_o_1 cma__c_prio_o_0 + cma__c_prio_n_0 +#define cma__c_prio_o_2 cma__c_prio_o_1 + cma__c_prio_n_1 +#define cma__c_prio_o_3 cma__c_prio_o_2 + cma__c_prio_n_2 +#define cma__c_prio_o_rt cma__c_prio_o_3 + cma__c_prio_n_3 + +/* + * Ada_low: These threads are queued in the background queues, thus there + * must be enough queues to allow one queue for each Ada priority below the + * Ada default. + */ +#define cma__c_prio_o_al cma__c_prio_o_bg + +/* + * Total number of ready queues, for declaration purposes + */ +#define cma__c_prio_n_tot \ + cma__c_prio_n_id + cma__c_prio_n_bg + cma__c_prio_n_rt \ + + cma__c_prio_n_0 + cma__c_prio_n_1 + cma__c_prio_n_2 + cma__c_prio_n_3 + +/* + * Formulae for determining a thread's priority. Variable priorities (such + * as foreground and background) are scaled values. + */ +#define cma__sched_priority(tcb) \ + ((tcb)->sched.class == cma__c_class_fore ? cma__sched_prio_fore (tcb) \ + :((tcb)->sched.class == cma__c_class_back ? cma__sched_prio_back (tcb) \ + :((tcb)->sched.class == cma__c_class_rt ? cma__sched_prio_rt (tcb) \ + :((tcb)->sched.class == cma__c_class_idle ? cma__sched_prio_idle (tcb) \ + :(cma__bugcheck ("cma__sched_priority: unrecognized class"), 0) )))) + +#define cma__sched_prio_fore(tcb) cma__sched_prio_fore_var (tcb) +#define cma__sched_prio_back(tcb) ((tcb)->sched.fixed_prio \ + ? cma__sched_prio_back_fix (tcb) : cma__sched_prio_back_var (tcb) ) +#define cma__sched_prio_rt(tcb) ((tcb)->sched.priority) +#define cma__sched_prio_idle(tcb) ((tcb)->sched.priority) + +#define cma__sched_prio_back_fix(tcb) \ + (cma__g_prio_bg_min + (cma__g_prio_bg_max - cma__g_prio_bg_min) \ + * ((tcb)->sched.priority + cma__c_prio_o_al - cma__c_prio_o_bg) \ + / cma__c_prio_n_bg) + +/* + * FIX-ME: Enable after modeling (if we like it) + */ +#if 1 +# define cma__sched_prio_fore_var(tcb) \ + ((cma__g_prio_fg_max + cma__g_prio_fg_min)/2) +# define cma__sched_prio_back_var(tcb) \ + ((cma__g_prio_bg_max + cma__g_prio_bg_min)/2) +#else +# define cma__sched_prio_back_var(tcb) cma__sched_prio_fore_var (tcb) + +# if 1 +/* + * Re-scale, since the division removes the scale factor. + * Scale and multiply before dividing to avoid loss of precision. + */ +# define cma__sched_prio_fore_var(tcb) \ + ((cma__g_vp_count * cma__scale_up((tcb)->sched.tot_time)) \ + / (tcb)->sched.cpu_time) +# else +/* + * Re-scale, since the division removes the scale factor. + * Scale and multiply before dividing to avoid loss of precision. + * Left shift the numerator to multiply by two. + */ +# define cma__sched_prio_fore_var(tcb) \ + (((cma__g_vp_count * cma__scale_up((tcb)->sched.tot_time) \ + * (tcb)->sched.priority * cma__g_init_frac_sum) << 1) \ + / ((tcb)->sched.cpu_time * (tcb)->sched.priority * cma__g_init_frac_sum \ + + (tcb)->sched.tot_time)) +# endif +#endif + +/* + * Update weighted-averaged, scaled tick counters + */ +#define cma__sched_update_time(ave, new) \ + (ave) = (ave) - ((cma__scale_dn((ave)) - (new)) << (cma__c_prio_scale - 4)) + +#define cma__sched_parameterize(tcb, policy) { \ + switch (policy) { \ + case cma_c_sched_fifo : { \ + (tcb)->sched.rtb = cma_c_true; \ + (tcb)->sched.spp = cma_c_true; \ + (tcb)->sched.fixed_prio = cma_c_true; \ + (tcb)->sched.class = cma__c_class_rt; \ + break; \ + } \ + case cma_c_sched_rr : { \ + (tcb)->sched.rtb = cma_c_false; \ + (tcb)->sched.spp = cma_c_true; \ + (tcb)->sched.fixed_prio = cma_c_true; \ + (tcb)->sched.class = cma__c_class_rt; \ + break; \ + } \ + case cma_c_sched_throughput : { \ + (tcb)->sched.rtb = cma_c_false; \ + (tcb)->sched.spp = cma_c_false; \ + (tcb)->sched.fixed_prio = cma_c_false; \ + (tcb)->sched.class = cma__c_class_fore; \ + break; \ + } \ + case cma_c_sched_background : { \ + (tcb)->sched.rtb = cma_c_false; \ + (tcb)->sched.spp = cma_c_false; \ + (tcb)->sched.fixed_prio = cma_c_false; \ + (tcb)->sched.class = cma__c_class_back; \ + break; \ + } \ + case cma_c_sched_ada_low : { \ + (tcb)->sched.rtb = cma_c_false; \ + (tcb)->sched.spp = cma_c_true; \ + (tcb)->sched.fixed_prio = cma_c_true; \ + (tcb)->sched.class = cma__c_class_back; \ + break; \ + } \ + case cma_c_sched_idle : { \ + (tcb)->sched.rtb = cma_c_false; \ + (tcb)->sched.spp = cma_c_false; \ + (tcb)->sched.fixed_prio = cma_c_false; \ + (tcb)->sched.class = cma__c_class_idle; \ + break; \ + } \ + default : { \ + cma__bugcheck ("cma__sched_parameterize: bad scheduling Policy"); \ + break; \ + } \ + } \ + } + +/* + * TYPEDEFS + */ + +/* + * Scheduling classes + */ +typedef enum CMA__T_SCHED_CLASS { + cma__c_class_rt, + cma__c_class_fore, + cma__c_class_back, + cma__c_class_idle + } cma__t_sched_class; + +/* + * GLOBAL DATA + */ + +/* + * Minimuma and maximum prioirities, for foreground and background threads, + * as of the last time the scheduler ran. (Scaled once.) + */ +extern cma_t_integer cma__g_prio_fg_min; +extern cma_t_integer cma__g_prio_fg_max; +extern cma_t_integer cma__g_prio_bg_min; +extern cma_t_integer cma__g_prio_bg_max; + +/* + * The "m" values are the slopes of the four sections of linear approximation. + * + * cma__g_prio_m_I = 4*N(I)/cma__g_prio_range (Scaled once.) + */ +extern cma_t_integer cma__g_prio_m_0, + cma__g_prio_m_1, + cma__g_prio_m_2, + cma__g_prio_m_3; + +/* + * The "b" values are the intercepts of the four sections of linear approx. + * (Not scaled.) + * + * cma__g_prio_b_I = -N(I)*(I*prio_max + (4-I)*prio_min)/prio_range + prio_o_I + */ +extern cma_t_integer cma__g_prio_b_0, + cma__g_prio_b_1, + cma__g_prio_b_2, + cma__g_prio_b_3; + +/* + * The "p" values are the end points of the four sections of linear approx. + * + * cma__g_prio_p_I = cma__g_prio_fg_min + (I/4)*cma__g_prio_range + * + * [cma__g_prio_p_0 is not defined since it is not used (also, it is the same + * as cma__g_prio_fg_min).] (Scaled once.) + */ +extern cma_t_integer cma__g_prio_p_1, + cma__g_prio_p_2, + cma__g_prio_p_3; + +/* + * Points to the next queue for the dispatcher to check for ready threads. + */ +extern cma_t_integer cma__g_next_ready_queue; + +/* + * Points to the queues of virtual processors (for preempt victim search) + */ +extern cma__t_queue cma__g_run_vps; +extern cma__t_queue cma__g_susp_vps; +extern cma_t_integer cma__g_vp_count; + +/* + * INTERNAL INTERFACES + */ + +#endif diff --git a/gdb/osf-share/cma_semaphore_defs.h b/gdb/osf-share/cma_semaphore_defs.h new file mode 100644 index 0000000000..e160de3394 --- /dev/null +++ b/gdb/osf-share/cma_semaphore_defs.h @@ -0,0 +1,46 @@ +/* + * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC. + * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY + * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION + * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems + * To anyone who acknowledges that this file is provided "AS IS" without + * any express or implied warranty: permission to use, copy, modify, and + * distribute this file for any purpose is hereby granted without fee, + * provided that the above copyright notices and this notice appears in + * all source code copies, and that none of the names listed above be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. None of these organizations + * makes any representations about the suitability of this software for + * any purpose. + */ +/* + * Header file for semaphore structure definition. + */ +#ifndef CMA_SEMAPHORE_DEFS +#define CMA_SEMAPHORE_DEFS + +/* + * INCLUDE FILES + */ +#include <cma.h> +#include <cma_queue.h> +#include <cma_defs.h> + +/* + * CONSTANTS AND MACROS + */ + +#define cma__c_semaphore_timeout 1 +#define cma__c_semaphore_event 0 +#define cma__c_select_timeout 2 + +/* + * TYPEDEFS + */ + +typedef struct CMA__T_SEMAPHORE { + cma__t_queue queue; + cma__t_atomic_bit nopending; + } cma__t_semaphore; + +#endif diff --git a/gdb/osf-share/cma_sequence.h b/gdb/osf-share/cma_sequence.h new file mode 100644 index 0000000000..8d362ed8d8 --- /dev/null +++ b/gdb/osf-share/cma_sequence.h @@ -0,0 +1,56 @@ +/* + * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC. + * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY + * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION + * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems + * To anyone who acknowledges that this file is provided "AS IS" without + * any express or implied warranty: permission to use, copy, modify, and + * distribute this file for any purpose is hereby granted without fee, + * provided that the above copyright notices and this notice appears in + * all source code copies, and that none of the names listed above be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. None of these organizations + * makes any representations about the suitability of this software for + * any purpose. + */ +/* + * Header file for sequence generator functions + */ + +#ifndef CMA_SEQUENCE +#define CMA_SEQUENCE + +/* + * INCLUDE FILES + */ + +/* + * CONSTANTS AND MACROS + */ + +/* + * TYPEDEFS + */ + +#ifndef __STDC__ +struct CMA__T_INT_MUTEX; +#endif + +typedef struct CMA__T_SEQUENCE { + struct CMA__T_INT_MUTEX *mutex; /* Serialize access to counter */ + cma_t_natural seq; /* Sequence number for object */ + } cma__t_sequence; + +/* + * GLOBAL DATA + */ + +/* + * INTERNAL INTERFACES + */ + +extern cma_t_natural cma__assign_sequence (cma__t_sequence *); + +extern void cma__init_sequence (cma__t_sequence *); + +#endif diff --git a/gdb/osf-share/cma_stack.h b/gdb/osf-share/cma_stack.h new file mode 100644 index 0000000000..97a41fd6e9 --- /dev/null +++ b/gdb/osf-share/cma_stack.h @@ -0,0 +1,83 @@ +/* + * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC. + * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY + * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION + * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems + * To anyone who acknowledges that this file is provided "AS IS" without + * any express or implied warranty: permission to use, copy, modify, and + * distribute this file for any purpose is hereby granted without fee, + * provided that the above copyright notices and this notice appears in + * all source code copies, and that none of the names listed above be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. None of these organizations + * makes any representations about the suitability of this software for + * any purpose. + */ +/* + * Header file for stack management + */ +#ifndef CMA_STACK +#define CMA_STACK + +/* + * INCLUDE FILES + */ + +#include <cma_tcb_defs.h> +#include <cma.h> +#include <cma_attr.h> +#include <cma_queue.h> +#include <cma_stack_int.h> + +/* + * CONSTANTS AND MACROS + */ + +#if _CMA_UNIPROCESSOR_ +# define cma__get_self_tcb() (cma__g_current_thread) +#endif + +/* + * Round the given value (a) upto cma__g_chunk_size + */ +#define cma__roundup_chunksize(a) (cma__roundup(a,cma__g_chunk_size)) + +/* + * TYPEDEFS + */ + +/* + * GLOBAL DATA + */ + +extern cma__t_list cma__g_stack_clusters; +extern cma__t_int_tcb *cma__g_current_thread; +extern cma_t_integer cma__g_chunk_size; + +/* + * INTERNAL INTERFACES + */ + +extern void cma__assign_stack (cma__t_int_stack *,cma__t_int_tcb *); + +extern void cma__free_stack (cma__t_int_stack *); + +extern void cma__free_stack_list (cma__t_queue *); + +#if !_CMA_UNIPROCESSOR_ +extern cma__t_int_tcb * cma__get_self_tcb (void); +#endif + +extern cma__t_int_tcb * cma__get_sp_tcb (cma_t_address); + +extern cma__t_int_stack * cma__get_stack (cma__t_int_attr *); + +extern void cma__init_stack (void); + +extern void cma__reinit_stack (cma_t_integer); + +#if _CMA_PROTECT_MEMORY_ +extern void cma__remap_stack_holes (void); +#endif + +#endif diff --git a/gdb/osf-share/cma_stack_int.h b/gdb/osf-share/cma_stack_int.h new file mode 100644 index 0000000000..bf76f60756 --- /dev/null +++ b/gdb/osf-share/cma_stack_int.h @@ -0,0 +1,136 @@ +/* + * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC. + * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY + * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION + * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems + * To anyone who acknowledges that this file is provided "AS IS" without + * any express or implied warranty: permission to use, copy, modify, and + * distribute this file for any purpose is hereby granted without fee, + * provided that the above copyright notices and this notice appears in + * all source code copies, and that none of the names listed above be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. None of these organizations + * makes any representations about the suitability of this software for + * any purpose. + */ +/* + * Header file for stack management (internal to cma_stack.c, but + * separate for convenience, and unit testing). + */ + +#ifndef CMA_STACK_INT +#define CMA_STACK_INT + +/* + * INCLUDE FILES + */ + +#include <cma.h> +#include <cma_queue.h> +#include <cma_list.h> +#include <cma_tcb_defs.h> + +/* + * CONSTANTS AND MACROS + */ + +#define cma___c_first_free_chunk 0 +#define cma___c_min_count 2 /* Smallest number of chunks to leave */ +#define cma___c_end (-1) /* End of free list (flag) */ +#define cma__c_yellow_size 0 + +/* + * Cluster types + */ +#define cma___c_cluster 0 /* Default cluster */ +#define cma___c_bigstack 1 /* Looks like a cluster, but it's a stack */ + + +#define cma___c_null_cluster (cma___t_cluster *)cma_c_null_ptr + + +/* + * TYPEDEFS + */ + +#ifndef __STDC__ +struct CMA__T_INT_STACK; +#endif + +typedef cma_t_natural cma___t_index; /* Type for chunk index */ + +typedef struct CMA___T_CLU_DESC { + cma__t_list list; /* Queue element for cluster list */ + cma_t_integer type; /* Type of cluster */ + cma_t_address stacks; + cma_t_address limit; + } cma___t_clu_desc; + +typedef union CMA___T_MAP_ENTRY { + struct { + cma__t_int_tcb *tcb; /* TCB associated with stack chunk */ + struct CMA__T_INT_STACK *stack; /* Stack desc. ass. with stack chunk */ + } mapped; + struct { + cma___t_index size; /* Number of chunks in block */ + cma___t_index next; /* Next free block */ + } free; + } cma___t_map_entry; + +/* + * NOTE: It is VERY IMPORTANT that both cma___t_cluster and cma___t_bigstack + * begin with the cma___t_clu_desc structure, as there is some code in the + * stack manager that relies on being able to treat both as equivalent! + */ +typedef struct CMA___T_CLUSTER { + cma___t_clu_desc desc; /* Describe this cluster */ + cma___t_map_entry map[cma__c_chunk_count]; /* thread map */ + cma___t_index free; /* First free chunk index */ + } cma___t_cluster; + +/* + * NOTE: It is VERY IMPORTANT that both cma___t_cluster and cma___t_bigstack + * begin with the cma___t_clu_desc structure, as there is some code in the + * stack manager that relies on being able to treat both as equivalent! + */ +typedef struct CMA___T_BIGSTACK { + cma___t_clu_desc desc; /* Describe this cluster */ + cma__t_int_tcb *tcb; /* TCB associated with stack */ + struct CMA__T_INT_STACK *stack; /* Stack desc. ass. with stack */ + cma_t_natural size; /* Size of big stack */ + cma_t_boolean in_use; /* Set if allocated */ + } cma___t_bigstack; + +#if _CMA_PROTECT_MEMORY_ +typedef struct CMA___T_INT_HOLE { + cma__t_queue link; /* Link holes together */ + cma_t_boolean protected; /* Set when pages are protected */ + cma_t_address first; /* First protected byte */ + cma_t_address last; /* Last protected byte */ + } cma___t_int_hole; +#endif + +typedef struct CMA__T_INT_STACK { + cma__t_object header; /* Common header (sequence, type info */ + cma__t_int_attr *attributes; /* Backpointer to attr obj */ + cma___t_cluster *cluster; /* Stack's cluster */ + cma_t_address stack_base; /* base address of stack */ + cma_t_address yellow_zone; /* first address of yellow zone */ + cma_t_address last_guard; /* last address of guard pages */ + cma_t_natural first_chunk; /* First chunk allocated */ + cma_t_natural chunk_count; /* Count of chunks allocated */ + cma__t_int_tcb *tcb; /* TCB backpointer */ +#if _CMA_PROTECT_MEMORY_ + cma___t_int_hole hole; /* Description of hole */ +#endif + } cma__t_int_stack; + +/* + * GLOBAL DATA + */ + +/* + * INTERNAL INTERFACES + */ + +#endif diff --git a/gdb/osf-share/cma_tcb_defs.h b/gdb/osf-share/cma_tcb_defs.h new file mode 100644 index 0000000000..6622050cf7 --- /dev/null +++ b/gdb/osf-share/cma_tcb_defs.h @@ -0,0 +1,269 @@ +/* + * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC. + * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY + * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION + * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems + * To anyone who acknowledges that this file is provided "AS IS" without + * any express or implied warranty: permission to use, copy, modify, and + * distribute this file for any purpose is hereby granted without fee, + * provided that the above copyright notices and this notice appears in + * all source code copies, and that none of the names listed above be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. None of these organizations + * makes any representations about the suitability of this software for + * any purpose. + */ +/* + * TCB-related type definitions. + */ + +#ifndef CMA_TCB_DEFS +#define CMA_TCB_DEFS + +/* + * INCLUDE FILES + */ +# if !_CMA_THREAD_SYNC_IO_ +# include <cma_thread_io.h> +# endif +#include <cma.h> +#include <cma_debug_client.h> +#include <cma_attr.h> +#include <cma_defs.h> +#include <cma_handle.h> +#include <cma_queue.h> +#if _CMA_OS_ == _CMA__UNIX +# if defined(SNI_DCOSX) +# include <sys/ucontext.h> +# endif +# include <signal.h> +#endif +#include <cma_sched.h> + +/* + * CONSTANTS AND MACROS + */ + +#if _CMA_PLATFORM_ == _CMA__IBMR2_UNIX +# define cma__c_ibmr2_ctx_stack_size 2048 +# define cma__c_ibmr2_ctx_stack_top (cma__c_ibmr2_ctx_stack_size - 1) +#endif + +/* + * TYPEDEFS + */ + +#ifndef __STDC__ +# if _CMA_HARDWARE_ != _CMA__HPPA +struct CMA__T_SEMAPHORE; +# endif +struct CMA__T_INT_CV; +struct CMA__T_INT_MUTEX; +struct CMA__T_INT_TCB; +#endif + +typedef cma_t_address *cma__t_context_list; + +typedef struct CMA__T_TCB_PAD { + /* + * Adjust to align the tcb prolog at byte 32. + * 12 bytes are required as object header is currently + * 20 bytes long. + */ + cma_t_integer pad1; /* pad bytes */ + cma_t_integer pad2; /* pad bytes */ + cma_t_integer pad3; /* pad bytes */ + } cma__t_tcb_pad; + +#if (_CMA_OS_ == _CMA__UNIX) && !_CMA_THREAD_SYNC_IO_ +typedef struct CMA__T_TCB_SELECT { + cma__t_queue queue; +#if (_CMA_UNIX_TYPE != _CMA__SVR4) + cma__t_file_mask *rfds; + cma__t_file_mask *wfds; + cma__t_file_mask *efds; +#else + cma__t_poll_info poll_info; +#endif /* (_CMA_UNIX_TYPE != _CMA__SVR4) */ + cma_t_integer nfound; + } cma__t_tcb_select; +#endif + +typedef struct CMA__T_TCB_TIME { + cma__t_queue queue; /* must be first entry! */ + cma_t_integer mode; + struct CMA__T_SEMAPHORE *semaphore; /* used for timed semaphores */ + cma_t_date_time wakeup_time; + cma_t_integer quanta_remaining; + } cma__t_tcb_time; + +typedef enum CMA__T_DEBEVT { + cma__c_debevt_activating = 1, /* First transition to running */ + cma__c_debevt_running = 2, /* Any transition to running */ + cma__c_debevt_preempting = 3, /* Preemted (replaced) another thread */ + cma__c_debevt_blocking = 4, /* Any transition to blocked */ + cma__c_debevt_terminating = 5, /* Final state transition */ + cma__c_debevt_term_alert = 6, /* Terminated due to alert/cancel */ + cma__c_debevt_term_exc = 7, /* Terminated due to exception */ + cma__c_debevt_exc_handled = 8 /* Exception is being handled */ + } cma__t_debevt; + +#define cma__c_debevt__first ((cma_t_integer)cma__c_debevt_activating) +#define cma__c_debevt__last ((cma_t_integer)cma__c_debevt_exc_handled) +#define cma__c_debevt__dim (cma__c_debevt__last + 1) + +/* + * Type defining thread substate, which is used by the debugger. + * If the state is blocked, substate indicates WHY the thread is blocked. + */ +typedef enum CMA__T_SUBSTATE { + cma__c_substa_normal = 0, + cma__c_substa_mutex = 1, + cma__c_substa_cv = 2, + cma__c_substa_timed_cv = 3, + cma__c_substa_term_alt = 4, + cma__c_substa_term_exc = 5, + cma__c_substa_delay =6, + cma__c_substa_not_yet_run = 7 + } cma__t_substate; +#define cma__c_substa__first ((cma_t_integer)cma__c_substa_normal) +#define cma__c_substa__last ((cma_t_integer)cma__c_substa_not_yet_run) +#define cma__c_substa__dim (cma__c_substa__last + 1) + + +/* + * Per-thread state for the debugger + */ +typedef struct CMA__T_TCB_DEBUG { + cma_t_boolean on_hold; /* Thread was put on hold by debugger */ + cma_t_boolean activated; /* Activation event was reported */ + cma_t_boolean did_preempt; /* Thread preempted prior one */ + cma_t_address start_pc; /* Start routine address */ + cma_t_address object_addr; /* Addr of thread object */ + cma__t_substate substate; /* Reason blocked, terminated, etc.*/ + cma_t_boolean notify_debugger;/* Notify debugger thread is running */ + cma_t_address SPARE2; /* SPARE */ + cma_t_address SPARE3; /* SPARE */ + struct CMA__T_INT_TCB + *preempted_tcb; /* TCB of thread that got preempted */ + cma_t_boolean flags[cma__c_debevt__dim]; + /* Events enabled for this thread */ + } cma__t_tcb_debug; + +typedef struct CMA__T_TCB_SCHED { + cma_t_integer adj_time; /* Abs. time in ticks of last prio adj */ + cma_t_integer tot_time; /* Weighted ave in ticks (scaled) */ + cma_t_integer time_stamp; /* Abs. time in ticks of last update */ + cma_t_integer cpu_time; /* Weighted average in ticks */ + cma_t_integer cpu_ticks; /* # of ticks while comp. (scaled) */ + cma_t_integer q_num; /* Number of last ready queue on */ + cma_t_priority priority; /* Thread priority */ + cma_t_sched_policy policy; /* Scheduling policy of thread */ + cma_t_boolean rtb; /* "Run 'Till Block" scheduling */ + cma_t_boolean spp; /* "Strict Priority Preemption" sched */ + cma_t_boolean fixed_prio; /* Fixed priority */ + cma__t_sched_class class; /* Scheduling class */ + struct CMA__T_VP *processor; /* Current processor (if running) */ + } cma__t_tcb_sched; + +typedef struct CMA__T_INT_ALERT { + cma_t_boolean pending : 1; /* alert_pending bit */ + cma_t_boolean g_enable : 1; /* general delivery state */ + cma_t_boolean a_enable : 1; /* asynchronous delivery state */ + cma_t_integer spare : 29; /* Pad to longword */ + cma_t_natural count; /* Alert scope nesting count */ + } cma__t_int_alert; + +typedef enum CMA__T_STATE { + cma__c_state_running = 0, /* For consistency with initial TCB */ + cma__c_state_ready = 1, + cma__c_state_blocked = 2, + cma__c_state_terminated = 3 + } cma__t_state; +#define cma__c_state__first ((cma_t_integer)cma__c_state_running) +#define cma__c_state__last ((cma_t_integer)cma__c_state_terminated) +#define cma__c_state__dim (cma__c_state__last + 1) + +typedef enum CMA__T_THKIND { + cma__c_thkind_initial = 0, /* Initial thread */ + cma__c_thkind_normal = 1, /* Normal thread */ + cma__c_thkind_null = 2 /* A null thread */ + } cma__t_thkind; +#define cma__c_thkind__first ((cma_t_integer)cma__c_thkind_initial) +#define cma__c_thkind__last ((cma_t_integer)cma__c_thkind_null) +#define cma__c_thkind__dim (cma__c_thkind__last + 1) + +typedef enum CMA__T_SYSCALL_STATE { + cma__c_syscall_ok = 1, /* syscall was not interrupted */ + cma__c_syscall_intintrpt = 1, /* syscall was interrupted by VTALRM */ + cma__c_syscall_extintrpt = 2 /* syscall was interrupted by external signal */ + } cma__t_syscall_state; + + +typedef struct CMA__T_INT_TCB { + /* + * Fixed part of TCB. + * Modifications to the following three fields must be coordinated. + * The object header must always be first, and the prolog must always + * remain at the same offset (32) for all time. Thus the object header + * must never grow beyond a maximum of 32 bytes. + */ + cma__t_object header; /* Common object header */ + cma__t_tcb_pad pad1; /* Pad required to align prolog */ + cma_t_tcb_prolog prolog; /* Standard prolog for tasks, threads */ + + /* + * Floating part of TCB (fields here on are free to be moved and resized). + */ + cma__t_queue threads; /* List of all known threads */ + cma__t_int_attr *attributes; /* Backpointer to attr obj */ + cma__t_state state; /* Current state of thread */ + cma__t_thkind kind; /* Which kind of thread */ + struct CMA__T_INT_MUTEX + *mutex; /* Mutex to control TCB access */ + struct CMA__T_INT_CV + *term_cv; /* CV for join */ + struct CMA__T_INT_MUTEX + *tswait_mutex; /* Mutex for thread-synchronous waits */ + struct CMA__T_INT_CV + *tswait_cv; /* CV for thread-synchronous waits */ + cma_t_start_routine start_code; /* Address of start routine */ + cma_t_address start_arg; /* Argument to pass to start_code */ + cma__t_queue stack; /* Queue header for stack descr. */ + cma_t_natural context_count; /* Size of context array */ + cma__t_context_list contexts; /* Context value array pointer */ + cma_t_exit_status exit_status; /* Exit status of thread */ + cma_t_address return_value; /* Thread's return value */ + cma__t_async_ctx async_ctx; /* Asynchronous context switch info */ + cma__t_static_ctx static_ctx; /* Static context switch information */ + cma_t_integer event_status; /* Status of semaphore operation */ + cma__t_tcb_time timer; /* Time info for dispatcher */ + cma__t_tcb_sched sched; /* Scheduler info */ + cma__t_tcb_debug debug; /* Debugger info */ +#if _CMA_OS_ == _CMA__UNIX +# if !_CMA_THREAD_SYNC_IO_ + cma__t_tcb_select select; /* Select info for timed selects */ +# endif + struct sigaction sigaction_data[NSIG]; +#endif + cma_t_natural syscall_state; /* set if one of the cma wrapped syscalls was interrupted. */ + cma_t_boolean detached; /* Set if already detached */ + cma_t_boolean terminated; /* Set if terminated */ + cma_t_integer joiners; /* Count of joiners, for zombie frees */ + cma__t_int_alert alert; /* Current alert state info */ + struct CMA__T_INT_CV + *wait_cv; /* CV thread is currently waiting on */ + struct CMA__T_INT_MUTEX + *wait_mutex; /* Mutex thread is waiting on */ + struct EXC_CONTEXT_T + *exc_stack; /* Top of exception stack */ +#if _CMA_PLATFORM_ == _CMA__IBMR2_UNIX + char ctx_stack[cma__c_ibmr2_ctx_stack_size]; +#endif + cma_t_integer thd_errno; /* Per-thread errno value */ +#if _CMA_OS_ == _CMA__VMS + cma_t_integer thd_vmserrno; /* Per-thread VMS errno value */ +#endif + } cma__t_int_tcb; + +#endif diff --git a/gdb/osf-share/cma_util.h b/gdb/osf-share/cma_util.h new file mode 100644 index 0000000000..00451c45a3 --- /dev/null +++ b/gdb/osf-share/cma_util.h @@ -0,0 +1,125 @@ +/* + * (c) Copyright 1990-1996 OPEN SOFTWARE FOUNDATION, INC. + * (c) Copyright 1990-1996 HEWLETT-PACKARD COMPANY + * (c) Copyright 1990-1996 DIGITAL EQUIPMENT CORPORATION + * (c) Copyright 1991, 1992 Siemens-Nixdorf Information Systems + * To anyone who acknowledges that this file is provided "AS IS" without + * any express or implied warranty: permission to use, copy, modify, and + * distribute this file for any purpose is hereby granted without fee, + * provided that the above copyright notices and this notice appears in + * all source code copies, and that none of the names listed above be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. None of these organizations + * makes any representations about the suitability of this software for + * any purpose. + */ +/* + * Header file for CMA internal UTIL operations + */ + +#ifndef CMA_UTIL +#define CMA_UTIL + +/* + * INCLUDE FILES + */ + +#include <cma.h> +#include <cma_attr.h> +#include <cma_defs.h> + +#if _CMA_OS_ == _CMA__VMS +# include <cma_rms.h> +#endif + +#if _CMA_VENDOR_ == _CMA__SUN +# include <sys/time.h> +#else +# include <time.h> +#endif + +#if _CMA_OS_ == _CMA__UNIX +# include <stdio.h> +#endif + +/* + * CONSTANTS AND MACROS + */ + +#define cma__c_buffer_size 256 /* Size of output buffer */ + +/* + * TYPEDEFS + */ + +/* + * Alternate eol routine + */ +typedef void (*cma__t_eol_routine) (char *); + +#if _CMA_OS_ == _CMA__VMS + typedef struct CMA__T_VMSFILE { + struct RAB rab; + struct FAB fab; + } cma__t_vmsfile, *cma__t_file; +#elif ( _CMA_UNIX_TYPE == _CMA__SVR4 ) + typedef int cma__t_file; +#else + typedef FILE *cma__t_file; +#endif + +/* + * GLOBAL DATA + */ + +/* + * INTERNAL INTERFACES + */ + +extern void cma__abort (void); + +extern cma_t_integer cma__atol (char *); + +extern cma_t_integer cma__atoi (char *); + +extern char * cma__getenv (char *,char *,int); + +extern int cma__gettimespec (struct timespec *); + +extern cma__t_file cma__int_fopen (char *,char *); + +#ifndef NDEBUG +extern void cma__init_trace (char *_env); +#endif + +extern char * cma__memcpy (char *,char *,cma_t_integer); + +#ifndef cma__memset +extern char * cma__memset (char *,cma_t_integer,cma_t_integer); +#endif + +extern void cma__putformat (char *,char *,...); + +extern void cma__putstring (char *,char *); + +extern void cma__putint (char *,cma_t_integer); + +extern void cma__putint_5 (char *,cma_t_integer); + +extern void cma__putint_10 (char *,cma_t_integer); + +extern void cma__puthex (char *,cma_t_integer); + +extern void cma__puthex_8 (char *,cma_t_integer); + +extern void cma__puteol (char *); + +extern void cma__set_eol_routine (cma__t_eol_routine,cma__t_eol_routine *); + +extern cma_t_integer cma__strlen (char *); + +extern int cma__strncmp (char *,char *,cma_t_integer); + +extern char *cma__gets (char *,char *); + +#endif |