From c6ad778bda302a9abfe3f1a905d1a80ee34c60a6 Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Mon, 26 Apr 2010 23:14:12 -0700 Subject: [PATCH] Remove omnithreads library. --- Makefile.common | 6 +- README.components | 150 ---- README.organization | 239 ------ config/Makefile.am | 3 +- config/gr_omnithread.m4 | 52 -- config/grc_omnithread.m4 | 46 - configure.ac | 5 - docs/doxygen/other/Makefile.am | 5 +- docs/doxygen/other/omnithread.html | 411 --------- docs/doxygen/other/omnithread.pdf | Bin 44848 -> 0 bytes docs/doxygen/other/omnithread.ps | 730 ---------------- gcell/apps/Makefile.am | 4 +- gcell/gcell.pc.in | 2 +- gnuradio-core/gnuradio-core.pc.in | 2 +- omnithread/.gitignore | 9 - omnithread/Makefile.am | 71 -- omnithread/README | 2 - omnithread/dir.mk | 229 ----- omnithread/gnuradio-omnithread.pc.in | 11 - omnithread/gnuradio/.gitignore | 2 - omnithread/gnuradio/Makefile.am | 32 - omnithread/gnuradio/omni_time.h | 89 -- omnithread/gnuradio/omnithread.h | 626 -------------- omnithread/gnuradio/ot_VxThread.h | 118 --- omnithread/gnuradio/ot_mach.h | 51 -- omnithread/gnuradio/ot_nt.h | 85 -- omnithread/gnuradio/ot_posix.h | 81 -- omnithread/gnuradio/ot_pthread_nt.h | 186 ----- omnithread/gnuradio/ot_solaris.h | 47 -- omnithread/mach.cc | 714 ---------------- omnithread/nt.cc | 969 --------------------- omnithread/omni_time.cc | 84 -- omnithread/posix.cc | 982 ---------------------- omnithread/solaris.cc | 615 -------------- omnithread/threaddata.cc | 83 -- omnithread/vxWorks.cc | 1160 -------------------------- usrp2/host/usrp2.pc.in | 2 +- 37 files changed, 7 insertions(+), 7896 deletions(-) delete mode 100755 README.components delete mode 100644 README.organization delete mode 100644 config/gr_omnithread.m4 delete mode 100644 config/grc_omnithread.m4 delete mode 100644 docs/doxygen/other/omnithread.html delete mode 100644 docs/doxygen/other/omnithread.pdf delete mode 100644 docs/doxygen/other/omnithread.ps delete mode 100644 omnithread/.gitignore delete mode 100644 omnithread/Makefile.am delete mode 100644 omnithread/README delete mode 100644 omnithread/dir.mk delete mode 100644 omnithread/gnuradio-omnithread.pc.in delete mode 100644 omnithread/gnuradio/.gitignore delete mode 100644 omnithread/gnuradio/Makefile.am delete mode 100644 omnithread/gnuradio/omni_time.h delete mode 100644 omnithread/gnuradio/omnithread.h delete mode 100644 omnithread/gnuradio/ot_VxThread.h delete mode 100644 omnithread/gnuradio/ot_mach.h delete mode 100644 omnithread/gnuradio/ot_nt.h delete mode 100644 omnithread/gnuradio/ot_posix.h delete mode 100644 omnithread/gnuradio/ot_pthread_nt.h delete mode 100644 omnithread/gnuradio/ot_solaris.h delete mode 100644 omnithread/mach.cc delete mode 100644 omnithread/nt.cc delete mode 100644 omnithread/omni_time.cc delete mode 100644 omnithread/posix.cc delete mode 100644 omnithread/solaris.cc delete mode 100644 omnithread/threaddata.cc delete mode 100644 omnithread/vxWorks.cc diff --git a/Makefile.common b/Makefile.common index 7854ed72..aafe85fe 100644 --- a/Makefile.common +++ b/Makefile.common @@ -55,17 +55,13 @@ libspudir = $(libdir)spu # This used to be set in configure.ac but is now defined here for all # Makefiles when this fragment is included. STD_DEFINES_AND_INCLUDES = $(DEFINES) $(BOOST_CPPFLAGS) \ - $(OMNITHREAD_INCLUDES) $(GNURADIO_INCLUDES) $(GRUEL_INCLUDES) + $(GNURADIO_INCLUDES) $(GRUEL_INCLUDES) # when including for compilation from pre-installed libraries and such, # need to make sure those are put last on the compile command WITH_INCLUDES = @with_INCLUDES@ WITH_SWIG_INCLUDES = @with_SWIG_INCLUDES@ -# How to link in the top-level omnithreads library from inside the tree -OMNITHREAD_INCLUDES = @omnithread_INCLUDES@ -OMNITHREAD_LA = @omnithread_LA@ - # Where to find gnuradio include files in the current build tree # top_srcdir for original stuff, top_builddir for generated files GNURADIO_INCLUDES = @gnuradio_core_INCLUDES@ diff --git a/README.components b/README.components deleted file mode 100755 index 996f2ee5..00000000 --- a/README.components +++ /dev/null @@ -1,150 +0,0 @@ -#!/bin/sh - -# $Id$ - -# Copyright 2008 Free Software Foundation. -# -# DO NOT RUN THIS SCRIPT UNTIL YOU UNDERSTAND IT!!! IT WILL REMOVE -# FILES ON YOUR SYSTEM. -# -# Read the script thoroughly before running it; it will *remove* -# /usr/local/gnuradio and repopulate it. -# -# This script provides a way to build GNU Radio modules individually, -# and both serves as an example of using the component build system -# and provides a way to test the build system. When run, it will -# build and install each GNU Radio module in turn, using the -# just-installed modules as prerequisites. It places the output of -# each build in a separate file BUILD.NNN.options, so that one can do -# 'tail -f BUILD.*' to see which components were successfully built. - -# This script is intended to be broadly portable; be careful when -# modifying not to cause problems on systems that place dependencies -# in other than /usr -# -# Besides GNU Radio dependencies, this program requires sudo, with a -# timer long enough to build each module (or no password requirement). -# - -set -x - -# Do not use /opt, because many systems do not have /opt and that -# risks running out of space in /. /usr/local/gnuradio is believed to -# be reasonable on all of *BSD and GNU/Linux. Probably this needs -# OS-specific overrides. -PREFIX=/usr/local/gnuradio - -echo "ABOUT TO COMPLETELY REMOVE $PREFIX in 10 SECONDS!" -sleep 10 - -echo -n "README.components START "; date - -# This file provides an example of how to build GNU Radio under pkgsrc. - -# Avoid using rm -rf with $PREFIX, which could be /. Make a backup of -# the old prefix. -sudo rm -rf $PREFIX.old -if [ -d $PREFIX ]; then - sudo mv $PREFIX $PREFIX.old -fi -rm -rf BUILD.* - -# Bootstrap just once, rather than once per module. -./bootstrap - -# Determine where prereqs come from. -export LDFLAGS= -export CPPFLAGS= -export PKG_CONFIG_PATH= -if [ -d /usr/pkg ]; then - # pkgsrc - LDFLAGS="$LDFLAGS -L/usr/pkg/lib -R/usr/pkg/lib" - CPPFLAGS="$CPPFLAGS -I/usr/pkg/include" - - # pkg-config is from pkgsrc, so already knows about /usr/pkg/lib/pkgconfig - PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$PREFIX/lib/pkgconfig" -fi - -echo LDFLAGS ,$LDFLAGS, -echo CPPFLAGS ,$CPPFLAGS, -echo PKG_CONFIG_PATH ,$PKG_CONFIG_PATH, - -# Determine number of cpus and thus how many jobs to run. -ncpus=1 -case x`uname` in - xNetBSD) - ncpus=`sysctl hw.ncpu|awk '{print $3}'` - ;; -esac -jflag=-j`expr $ncpus \* 2` - -# These are currently ignored. -CONF_DOC_ARGS=" ---enable-doxygen ---enable-dot ---enable-latex-docs -" -CONF_DISABLE_ALL="--disable-all-components" - -# We use % instead of ' ' to be able to iterate with /bin/sh's for. -# This variable should list all possible arguments, in tsorted order. -CONF_ENABLE_ARGS=" ---enable-omnithread ---with-omnithread%--enable-gnuradio-core ---with-omnithread%--enable-pmt ---with-omnithread%--with-pmt%--enable-mblock ---with-omnithread%--with-pmt%--with-mblock%--enable-usrp ---with-omnithread%--with-gnuradio-core%--with-pmt%--with-mblock%--with-usrp%--enable-gr-usrp ---with-omnithread%--with-gnuradio-core%--with-pmt%--with-mblock%--enable-gr-msdd6000 ---with-omnithread%--with-gnuradio-core%--with-pmt%--with-mblock%--enable-gr-audio-alsa ---with-omnithread%--with-gnuradio-core%--with-pmt%--with-mblock%--enable-gr-audio-jack ---with-omnithread%--with-gnuradio-core%--with-pmt%--with-mblock%--enable-gr-audio-oss ---with-omnithread%--with-gnuradio-core%--with-pmt%--with-mblock%--enable-gr-audio-osx ---with-omnithread%--with-gnuradio-core%--with-pmt%--with-mblock%--enable-gr-audio-portaudio ---with-omnithread%--with-gnuradio-core%--with-pmt%--with-mblock%--enable-gr-audio-windows ---with-omnithread%--with-gnuradio-core%--with-pmt%--with-mblock%--enable-gr-atsc ---with-omnithread%--with-gnuradio-core%--with-pmt%--with-mblock%--enable-gr-comedi ---with-omnithread%--with-gnuradio-core%--with-pmt%--with-mblock%--enable-gr-cvsd-vocoder ---with-omnithread%--with-gnuradio-core%--with-pmt%--with-mblock%--with-usrp%--enable-gr-gpio ---with-omnithread%--with-gnuradio-core%--with-pmt%--with-mblock%--enable-gr-gsm-fr-vocoder ---with-omnithread%--with-gnuradio-core%--with-pmt%--with-mblock%--enable-gr-pager ---with-omnithread%--with-gnuradio-core%--with-pmt%--with-mblock%--with-usrp%--enable-gr-radar-mono ---with-omnithread%--with-gnuradio-core%--with-pmt%--with-mblock%--enable-gr-radio-astronomy ---with-omnithread%--with-gnuradio-core%--with-pmt%--with-mblock%--enable-gr-trellis ---with-omnithread%--with-gnuradio-core%--with-pmt%--with-mblock%--enable-gr-video-sdl ---with-omnithread%--with-gnuradio-core%--with-pmt%--with-mblock%--enable-gr-wxgui ---with-omnithread%--with-gnuradio-core%--with-pmt%--with-mblock%--with-usrp%--enable-gr-sounder ---with-omnithread%--with-gnuradio-core%--with-pmt%--with-mblock%--with-usrp%--with-gr-usrp%--with-gr-wxgui%--enable-gr-utils ---with-omnithread%--with-gnuradio-core%--with-pmt%--with-mblock%--enable-gnuradio-examples -" - -seq=0 -for arg in $CONF_ENABLE_ARGS; do - - # Convert sequence numbers and arguments to usable values. - seqprint=`printf "%03d" $seq` - argspace=`echo $arg | sed -e 's/%/ /g'` - - echo "BUILDING WITH $argspace" - - ( - # configure with just one module - ./configure --prefix=$PREFIX $CONF_DISABLE_ALL $argspace && - - # remove all prior objects - make clean && - - # build - make $jflag && - - # install - sudo make install && - - echo "SUCCEEDED $argspace" - - ) > BUILD.$seqprint.$arg 2>&1 - - seq=`expr $seq + 1` -done - -echo -n "README.components FINISH "; date diff --git a/README.organization b/README.organization deleted file mode 100644 index 138d9018..00000000 --- a/README.organization +++ /dev/null @@ -1,239 +0,0 @@ -[This file is currently not baked and does not claim to represent -consensus.] - -* Introduction - -This file describes the current organization of the GNU Radio source -tree. It is intended to be both descriptive and normative. - -* Unresolved issues in organization - -The big issues are: - -1) Should we separate by "code needed to implement protocol/modulation -foo", or related blocks. to (that are therefore not so likely to be -used together). - -2) How do m-blocks impact organization? If m-blocks are in a separate -module, which seems reasonable, then do we have most modules depend on -m-blocks rather than just core, or do we have two versions of blocks - -the classic continuous block and the m-block wrapped block? If -m-blocks become the main path, what will be less awkward? - -3) Because some (ADROIT at BBN) have proposed to implement MACs in -click instead of GNU Radio, should we have a clean separation of -MAC/PHY within GNU Radio, to facilitate using MACs implemented in -various places? - -4) Examples abound, and many are in gnuradio-examples. It might be -better to put examples near the code they use, and to separate useful -programs (like USRP benchmarks) from true examples. Examples should -probably be installed in $prefix/share/examples/gnuradio. - -* Plan (normative) [[NOT BAKED!!! NO CONSENSUS!!!]] - -Create a new module gr-packet, to hold blocks generally relevant to -sending blocks of data. Create subdirectories within gr-packet for -specific protocols (e.g. 802.11, GNU Radio's GMSK "protocol"). - -Convert tunnel.py to be OS-independent and a general source/sink -block, decoupling modulation from OS plumbing. - -* Pointers to code to be integrated - -The immediate question is how to integrate the 802.11 implementation -done by BBN (and assigned to FSF), available at: - - http://acert.ir.bbn.com/viewvc/adroitgrdevel/adroitgrdevel/gr-bbn/ - -This contains blocks at various places in the stack, and gdt believs -that putting them in an 802.11 module will lead to less reuse and less -of a tendency to generalize. - -* Organization of the GNU Radio source tree (mostly descriptive) - -The GNU Radio source tree is rooted at the directory containing this -file; see README for how to get it if you're using a release or -tarball. - -Within this directory, there are a number of subdirectories, most of -which can be enabled or disabled independently. See README for how to -do that; this document is concerned with describing what each module -does enough to help someone who is familiar enough with GNU Radio to -write new code to choose where to put it. The list is not exhaustive. -The description of some modules also lists things that don't belong, -tagged with ?M. - -** gnuradio-core [foundational code for the rest of GNU Radio] - -(gen_interpolator_taps is not installed. Why? How is it used?) - -doc: glue to use with doxygen - -?M doc/other/tv-channel-frequencies: (TV specific) - -?M src/lib/g72x: - G.711 family codec - -src/lib/filter: - implementation and coefficient generation -src/lib/general: - foundational blocks not specific to any technology: - type conversion, {de,}vectorization, add, sub - rms power, throttle, sources, sinks, squelch base class - - general blocks: - agc, pll, sync, costas loop, power squelch, quadrature demod - - ?M framer/correlator - ?M packet source/sink - -src/lib/io: - basic file io, message io - oscope (trigger support) - i2c bus - ?M microtune eval board (like USRP; should probably have own module) - ?M SDR1000 - -src/lib/omnithread: - portable threading library (for when POSIX isn't portable enough) - -src/lib/reed-solomon: - reed-solomon implementation. Unclear how/whether it's wrapped into - blocks. - -src/lib/runtime: - blocks (basic, hier) and associated buffering - flowgraphs - timers - doubly-mapped circular buffers - -src/lib/swig: - code to wrap the rest in python - ?M atsc.i (cruft? moved?) - -src/python: - build utilities - -src/python/bin: - ?M microtune.py: microtune control program (installed and EXTRA_DIST!) - -src/python/gnuradio: - audio base class - engineering notation support - test harness support - test code (not installed) - basic block/flow_graph - -src/tests: - test code - ?M test_atsc.cc (# in Makefile.am, but still present) - -src/utils: - octave and Scheme scripts (not installed) - -** usrp - -This contains code to deal with the USRP, but not GNU Radio support. - -?M fusb - The "fusb" abstraction is arguably useful for all interface devices - that use USB, not just the USRP. - -** gr-usrp - -Code to use the USRP with GNU Radio. - -?M Arguably the Gnu Radio/USRP benchmarks belong here, but are in -examples - -** gr-audio-alsa -** gr-audio-jack -** gr-audio-oss -** gr-audio-osx -** gr-audio-portaudio -** gr-audio-windows - [All of these support audio for some particular audio backend. - -** gr-atsc - ATSC (HDTV) transmitter and receiver. - All blocks seem to be specific to ATSC. - ?M Perhaps some blocks should be abstracted out for reuse with other - than ATSC parameters. - -** gr-comedi - This module is missing a README that explains what it does. - http://www.comedi.org/ - -** gr-gsm-fr-vocoder - GSM 06.10 full rate vocoder, and gsm library - (Note that the presence of this argues for moving the G.711 code discussed above.) - -** gr-pager - POCSAG and FLEX - (gdt suspects there are blocks in here that could be generalized.) - -** gr-radio-astronomy - seems to use only standard blocks from python - -** gr-trellis - This module provides trellis code support, and appears generic. - -** gr-video-sdl - This appears to be like the audio modules, but for video and - specifically for SDL. Unlike audio which has a base class, there - does not appear to be an abstract video class in gnuradio-core. - -** gr-wxgui - Support for using wxwidgets from python. - ?M (Linux-specific??) code to use the Griffin Powermate (and hook it to a GUI) - glue to connect FFT and scope to gui - -** pmt - polymorphic types (building block) - -** mblock - Message block implementation. - Note that mblock being a module means that signal processing blocks - that are mblock-aware must depend on this module and thus probably - cannot be in gnuradio-core. Thus, m-block wrappers for the blocks - in gnuradio-core must be elsewhere and it is maybe a good idea to - move them to someplace like gnuradio-common where the streaming and - m-block versions can be together. - -** ezdop - Code to deal with the ezdop direction-finding hardware. - -** gr-ezdop - Glue code to use the ezdop from GNU Radio. - -** gr-rdf - (Currently empty) code to perform direction finding. - -** gnuradio-examples - - It's arguable that all of these are misplaced, and that examples - belong with the code that they use. - - Bona fide examples (code not intended to be useful except for reading): - c++/dial_tone (how to do things only in C++) - python/audio - - Test programs: - python/channel-coding - python/digital-voice - python/multi-antenna (?) - - Programs in between test and useful: - python/digital - ?M tunnel.py: glue to get packets to Linux, conflates modulation - and packet handling - python/multi_usrp - python/networking/measurement_slave (goes with what?) - - ?M Programs intended to be useful - python/apps/hf_{explorer,radio} - - ?M Kitchen sink: - python/usrp - benchmarks, test, basic fm/wfm/tv receivers, spectrum sensing, - fft, oscope diff --git a/config/Makefile.am b/config/Makefile.am index 46038cba..959b8f01 100644 --- a/config/Makefile.am +++ b/config/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2001,2006,2008,2009 Free Software Foundation, Inc. +# Copyright 2001,2006,2008,2009,2010 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -86,7 +86,6 @@ m4macros = \ gr_lib64.m4 \ gr_libgnuradio_core_extra_ldflags.m4 \ gr_no_undefined.m4 \ - gr_omnithread.m4 \ gr_pwin32.m4 \ gr_python.m4 \ gr_require_mc4020.m4 \ diff --git a/config/gr_omnithread.m4 b/config/gr_omnithread.m4 deleted file mode 100644 index 054f0782..00000000 --- a/config/gr_omnithread.m4 +++ /dev/null @@ -1,52 +0,0 @@ -# Check for Omnithread (pthread/NT) thread support. -*- Autoconf -*- - -# Copyright 2003,2007 Free Software Foundation, Inc. - -# 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 3, 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., 51 Franklin Street, Boston, MA -# 02110-1301, USA. - -AC_DEFUN([GR_OMNITHREAD], -[ - # Check first for POSIX - ACX_PTHREAD( - [ AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]) - ot_posix="yes" - DEFINES="$DEFINES -DOMNITHREAD_POSIX=1" - ],[ - # If no POSIX support found, then check for NT threads - AC_MSG_CHECKING([for NT threads]) - - AC_LINK_IFELSE([ - #include - #include - int main() { InitializeCriticalSection(NULL); return 0; } - ], - [ - ot_nt="yes" - DEFINES="$DEFINES -DOMNITHREAD_NT=1" - ], - [AC_MSG_FAILURE([GNU Radio requires POSIX threads. pthreads not found.])] - ) - AC_MSG_RESULT(yes) - ]) - AM_CONDITIONAL(OMNITHREAD_POSIX, test "x$ot_posix" = xyes) - AM_CONDITIONAL(OMNITHREAD_NT, test "x$ot_nt" = xyes) - - save_LIBS="$LIBS" - AC_SEARCH_LIBS([clock_gettime], [rt], [PTHREAD_LIBS="$PTHREAD_LIBS $LIBS"]) - AC_CHECK_FUNCS([clock_gettime gettimeofday nanosleep]) - LIBS="$save_LIBS" -]) - diff --git a/config/grc_omnithread.m4 b/config/grc_omnithread.m4 deleted file mode 100644 index 1bcedebe..00000000 --- a/config/grc_omnithread.m4 +++ /dev/null @@ -1,46 +0,0 @@ -dnl Copyright 2001,2002,2003,2004,2005,2006,2007,2008 Free Software Foundation, Inc. -dnl -dnl This file is part of GNU Radio -dnl -dnl GNU Radio is free software; you can redistribute it and/or modify -dnl it under the terms of the GNU General Public License as published by -dnl the Free Software Foundation; either version 3, or (at your option) -dnl any later version. -dnl -dnl GNU Radio is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -dnl GNU General Public License for more details. -dnl -dnl You should have received a copy of the GNU General Public License -dnl along with GNU Radio; see the file COPYING. If not, write to -dnl the Free Software Foundation, Inc., 51 Franklin Street, -dnl Boston, MA 02110-1301, USA. - -AC_DEFUN([GRC_OMNITHREAD],[ - GRC_ENABLE(omnithread) - - GRC_WITH(omnithread, [], gnuradio-omnithread) - - dnl If execution gets to here, $passed will be: - dnl with : if the --with code didn't error out - dnl yes : if the --enable code passed muster and all dependencies are met - dnl no : otherwise - if test $passed != with; then - dnl how and where to find INCLUDES and LA and such - omnithread_INCLUDES="-I\${abs_top_srcdir}/omnithread" - omnithread_LA="\${abs_top_builddir}/omnithread/libgromnithread.la" - omnithread_LIBDIRPATH="\${abs_top_builddir}/omnithread:\${abs_top_builddir}/omnithread/.libs" - fi - - AC_CONFIG_FILES([ \ - omnithread/Makefile \ - omnithread/gnuradio/Makefile \ - omnithread/gnuradio-omnithread.pc - ]) - - GRC_BUILD_CONDITIONAL(omnithread,[ - dnl run_tests is created from run_tests.in. Make it executable. - dnl AC_CONFIG_COMMANDS([run_tests_omnithread], [chmod +x omnithread/run_tests]) - ]) -]) diff --git a/configure.ac b/configure.ac index 7b90676a..a1709338 100644 --- a/configure.ac +++ b/configure.ac @@ -149,9 +149,6 @@ AM_CONDITIONAL([HAS_XMLTO], [test x$XMLTO = xyes]) dnl Checks for libraries. AC_CHECK_LIB(socket,socket) -dnl check for omnithreads (will soon be removed) -GR_OMNITHREAD - dnl Set the c++ compiler that we use for the build system when cross compiling if test x$CXX_FOR_BUILD = x then @@ -339,7 +336,6 @@ AC_ARG_ENABLE( build_dirs="config" GRC_GRUEL dnl must come first -GRC_OMNITHREAD dnl must come before gnuradio-core and mblock GRC_GCELL GRC_GNURADIO_CORE GRC_USRP @@ -347,7 +343,6 @@ GRC_USRP2 GRC_VRT GRC_GR_USRP dnl this must come after GRC_USRP GRC_GR_USRP2 -dnl GRC_GR_VRT GRC_GR_GCELL dnl this must come after GRC_GCELL and GRC_GNURADIO_CORE GRC_GR_MSDD6000 GRC_GR_AUDIO_ALSA diff --git a/docs/doxygen/other/Makefile.am b/docs/doxygen/other/Makefile.am index 5e05d5d3..eb5f170a 100644 --- a/docs/doxygen/other/Makefile.am +++ b/docs/doxygen/other/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2001,2004 Free Software Foundation, Inc. +# Copyright 2001,2004,2010 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -24,9 +24,6 @@ include $(top_srcdir)/Makefile.common EXTRA_DIST = \ doxypy.py \ group_defs.dox \ - omnithread.html \ - omnithread.pdf \ - omnithread.ps \ shared_ptr_docstub.h \ tv-channel-frequencies \ vector_docstub.h diff --git a/docs/doxygen/other/omnithread.html b/docs/doxygen/other/omnithread.html deleted file mode 100644 index 5682d1d0..00000000 --- a/docs/doxygen/other/omnithread.html +++ /dev/null @@ -1,411 +0,0 @@ - - -The OMNI Thread Abstraction - - - - - - - - - - - - -

The OMNI Thread Abstraction

- -

Tristan Richardson
-AT&T Laboratories Cambridge
-

- -

Revised November 2001

- - -

1  Introduction

- -The OMNI thread abstraction is designed to provide a common set of -thread operations for use in programs written in C++. Programs -written using the abstraction should be much easier to port between -different architectures with different underlying threads primitives.
-
-The programming interface is designed to be similar to the C language -interface to POSIX threads (IEEE draft standard 1003.1c --- previously -1003.4a, often known as ``pthreads'' [POSIX94]).
-
-Much of the abstraction consists of simple C++ object wrappers around -pthread calls. However for some features such as thread-specific -data, a better interface can be offered because of the use of C++.
-
-Some of the more complex features of pthreads are not supported -because of the difficulty of ensuring the same features can be offered -on top of other thread systems. Such features include thread -cancellation and complex scheduling control (though simple thread -priorities are supported).
-
-The abstraction layer is currently implemented for the following -architectures / thread systems: -
  • Solaris 2.x using pthreads draft 10 -
  • Solaris 2.x using solaris threads (but pthreads version is now standard) -
  • Alpha OSF1 using pthreads draft 4 -
  • Windows NT using NT threads -
  • Linux 2.x using Linuxthread 0.5 (which is based on pthreads draft 10) -
  • Linux 2.x using MIT pthreads (which is based on draft 8) -
  • ATMos using pthreads draft 6 (but not Virata ATMos)
-See the omnithread.h header file for full details of the API. -The descriptions below assume you have some previous knowledge of -threads, mutexes, condition variables and semaphores. Also refer to -other documentation ([Birrell89], [POSIX94]) for further -explanation of these ideas (particularly condition variables, the use -of which may not be particularly intuitive when first encountered).
-
- - -

2  Synchronisation objects

- -Synchronisation objects are used to synchronise threads within the -same process. There is no inter-process synchronisation provided. -The synchronisation objects provided are mutexes, condition variables -and counting semaphores.
-
- - -

2.1  Mutex

- -An object of type omni_mutex is used for mutual exclusion. -It provides two operations, lock() and unlock(). -The alternative names acquire() and release() can be -used if preferred. Behaviour is undefined when a thread attempts to -lock the same mutex again or when a mutex is locked by one thread and -unlocked by a different thread.
-
- - -

2.2  Condition Variable

- -A condition variable is represented by an omni_condition and -is used for signalling between threads. A call to wait() -causes a thread to wait on the condition variable. A call to -signal() wakes up at least one thread if any are waiting. A -call to broadcast() wakes up all threads waiting on the -condition variable.
-
-When constructed, a pointer to an omni_mutex must be given. -A condition variable wait() has an implicit mutex -unlock() and lock() around it. The link between -condition variable and mutex lasts for the lifetime of the condition -variable (unlike pthreads where the link is only for the duration of -the wait). The same mutex may be used with several condition -variables.
-
-A wait with a timeout can be achieved by calling -timed_wait(). This is given an absolute time to wait until. -The routine omni_thread::get_time() can be used to turn a -relative time into an absolute time. timed_wait() returns -true if the condition was signalled, false if the -time expired before the condition variable was signalled.
-
- - -

2.3  Counting semaphores

- -An omni_semaphore is a counting semaphore. When created it -is given an initial unsigned integer value. When wait() is -called, the value is decremented if non-zero. If the value is zero -then the thread blocks instead. When post() is called, if -any threads are blocked in wait(), exactly one thread is -woken. If no threads were blocked then the value of the semaphore is -incremented.
-
-If a thread calls try_wait(), then the thread won't block if -the semaphore's value is 0, returning false instead.
-
-There is no way of querying the value of the semaphore.
-
- - -

3  Thread object

- -A thread is represented by an omni_thread object. There are -broadly two different ways in which it can be used.
-
-The first way is simply to create an omni_thread object, -giving a particular function which the thread should execute. This is -like the POSIX (or any other) C language interface.
-
-The second method of use is to create a new class which inherits from -omni_thread. In this case the thread will execute the -run() member function of the new class. One advantage of -this scheme is that thread-specific data can be implemented simply by -having data members of the new class.
-
-When constructed a thread is in the "new" state and has not actually -started. A call to start() causes the thread to begin -executing. A static member function create() is provided to -construct and start a thread in a single call. A thread exits by -calling exit() or by returning from the thread function.
-
-Threads can be either detached or undetached. Detached threads are -threads for which all state will be lost upon exit. Other threads -cannot determine when a detached thread will disappear, and therefore -should not attempt to access the thread object unless some explicit -synchronisation with the detached thread guarantees that it still -exists.
-
-Undetached threads are threads for which storage is not reclaimed -until another thread waits for its termination by calling -join(). An exit value can be passed from an undetached -thread to the thread which joins it.
-
-Detached / undetached threads are distinguished on creation by the -type of function they execute. Undetached threads execute a function -which has a void* return type, whereas detached threads -execute a function which has a void return type. -Unfortunately C++ member functions are not allowed to be distinguished -simply by their return type. Thus in the case of a derived class of -omni_thread which needs an undetached thread, the member -function executed by the thread is called run_undetached() -rather than run(), and it is started by calling -start_undetached() instead of start().
-
-The abstraction currently supports three priorities of thread, but no -guarantee is made of how this will affect underlying thread -scheduling. The three priorities are PRIORITY_LOW, -PRIORITY_NORMAL and PRIORITY_HIGH. By default all -threads run at PRIORITY_NORMAL. A different priority can be -specified on thread creation, or while the thread is running using -set_priority(). A thread's current priority is returned by -priority().
-
-Other functions provided are self() which returns the calling -thread's omni_thread object, yield() which -requests that other threads be allowed to run, id() which -returns an integer id for the thread for use in debugging, -state(), sleep() and get_time().
-
- - -

4  Per-thread data

- -omnithread supports per-thread data, via member functions of the -omni_thread object.
-
-First, you must allocate a key for with the -omni_thread::allocate_key() function. Then, any object -whose class is derived from omni_thread::value_t can be -stored using the set_value() function. Values are retrieved -or removed with get_value() and remove_value() -respectively.
-
-When the thread exits, all per-thread data is deleted (hence the base -class with virtual destructor).
-
-Note that the per-thread data functions are not thread safe, -so although you can access one thread's storage from another thread, -there is no concurrency control. Unless you really know what you are -doing, it is best to only access per-thread data from the thread it is -attached to.
-
- - -

5  Using OMNI threads in your program

- -Obviously you need to include the omnithread.h header file in -your source code, and link in the omnithread library with your -executable. Because there is a single omnithread.h for all -platforms, certain preprocessor defines must be given as compiler -options. The easiest way to do this is to study the makefiles given -in the examples provided with this distribution. If you are to -include OMNI threads in your own development environment, these are -the necessary preprocessor defines:
- - - - - - - - - - - - - - - - - - - - - - - - -
PlatformPreprocessor Defines
Sun Solaris 2.x-D__sunos__ -D__sparc__ -D__OSVERSION__=5
 -DSVR4 -DUsePthread -D_REENTRANT
x86 Linux 2.0-D__linux__ -D__i86__ -D__OSVERSION__=2
with linuxthreads 0.5-D_REENTRANT
Digital Unix 3.2-D__osf1__ -D__alpha__ -D__OSVERSION__=3
 -D_REENTRANT
Windows NT-D__NT__ -MD

- - -

6  Threaded I/O shutdown for Unix

- -or, how one thread should tell another thread to shut down when it -might be doing a blocking call on a socket.
-
-If you are using omniORB, you don't need to worry about all -this, since omniORB does it for you. This section is only relevant -if you are using omnithread in your own socket-based programming. It -is also seriously out of date.
-
-Unfortunately there doesn't seem to be a standard way of doing this -which works across all Unix systems. I have investigated the -behaviour of Solaris 2.5 and Digital Unix 3.2. On Digital Unix -everything is fine, as the obvious method using shutdown() seems to -work OK. Unfortunately on Solaris shutdown can only be used on a -connected socket, so we need devious means to get around this -limitation. The details are summarised below:
-
- - -

6.1  read()

- -Thread A is in a loop, doing read(sock), processing the data, -then going back into the read.
-
-Thread B comes along and wants to shut it down --- it can't cancel -thread A since (i) working out how to clean up according to where A is -in its loop is a nightmare, and (ii) this isn't available in -omnithread anyway.
-
-On Solaris 2.5 and Digital Unix 3.2 the following strategy works:
-
-Thread B does shutdown(sock,2).
-
-At this point thread A is either blocked inside read(sock), or -is elsewhere in the loop. If the former then read will return 0, -indicating that the socket is closed. If the latter then eventually -thread A will call read(sock) and then this will return 0. -Thread A should close(sock), do any other tidying up, and exit.
-
-If there is another point in the loop that thread A can block then -obviously thread B needs to be aware of this and be able to wake it up -in the appropriate way from that point.
-
- - -

6.2  accept()

- -Again thread A is in a loop, this time doing an accept on listenSock, -dealing with a new connection and going back into accept. Thread B -wants to cancel it.
-
-On Digital Unix 3.2 the strategy is identical to that for read:
-
-Thread B does shutdown(listenSock,2). Wherever thread A is in -the loop, eventually it will return ECONNABORTED from the -accept call. It should close(listenSock), tidy up as necessary -and exit.
-
-On Solaris 2.5 thread B can't do shutdown(listenSock,2) --- -this returns ENOTCONN. Instead the following strategy can be -used:
-
-First thread B sets some sort of "shutdown flag" associated with -listenSock. Then it does getsockaddr(listenSock) to find out -which port listenSock is on (or knows already), sets up a socket -dummySock, does connect(dummySock, this host, port) and -finally does close(dummySock).
-
-Wherever thread A is in the loop, eventually it will call -accept(listenSock). This will return successfully with a new -socket, say connSock. Thread A then checks to see if the "shutdown -flag" is set. If not, then it's a normal connection. If it is set, -then thread A closes listenSock and connSock, tidies up and exits.
-
- - -

6.3  write()

- -Thread A may be blocked in write, or about to go in to a -potentially-blocking write. Thread B wants to shut it down.
-
-On Solaris 2.5:
-
-Thread B does shutdown(sock,2).
-
-If thread A is already in write(sock) then it will return with -ENXIO. If thread A calls write after thread B calls shutdown -this will return EIO.
-
-On Digital Unix 3.2:
-
-Thread B does shutdown(sock,2).
-
-If thread A is already in write(sock) then it will return the -number of bytes written before it became blocked. A subsequent call -to write will then generate SIGPIPE (or EPIPE will be -returned if SIGPIPE is ignored by the thread).
-
- - -

6.4  connect()

- -Thread A may be blocked in connect, or about to go in to a -potentially-blocking connect. Thread B wants to shut it down.
-
-On Digital Unix 3.2:
-
-Thread B does shutdown(sock,2).
-
-If thread A is already in connect(sock) then it will return a -successful connection. Subsequent reading or writing will show that -the socket has been shut down (i.e. read returns 0, write generates -SIGPIPE or returns EPIPE). If thread A calls connect -after thread B calls shutdown this will return EINVAL.
-
-On Solaris 2.5:
-
-There is no way to wake up a thread which is blocked in connect. -Instead Solaris forces us through a ridiculous procedure whichever way -we try it. One way is this:
-
-First thread A creates a pipe in addition to the socket. Instead of -shutting down the socket, thread B simply writes a byte to the pipe.
-
-Thread A meanwhile sets the socket to non-blocking mode using -fcntl(sock, F_SETFL, O_NONBLOCK). Then it calls connect -on the socket --- this will return EINPROGRESS. Then it must -call select(), waiting for either sock to become writable or -for the pipe to become readable. If select returns that just sock is -writable then the connection has succeeded. It then needs to set the -socket back to blocking mode using fcntl(sock, F_SETFL, 0). If -instead select returns that the pipe is readable, thread A closes the -socket, tidies up and exits.
-
-An alternative method is similar but to use polling instead of the -pipe. Thread B justs sets a flag and thread A calls select with a -timeout, periodically waking up to see if the flag has been set.
-
- - -

References

-
[POSIX94]
-Portable Operating System Interface (POSIX) Threads Extension, -P1003.1c Draft 10, -IEEE, -September 1994.
-
-
[Birrell89]
-An Introduction to Programming with Threads, -Research Report 35, -DEC Systems Research Center, -Palo Alto, CA, -January 1989.
- - - -
-
This document was translated from LATEX by -HEVEA. -
- - diff --git a/docs/doxygen/other/omnithread.pdf b/docs/doxygen/other/omnithread.pdf deleted file mode 100644 index b0033072ff459f90ebda6cc8a570c56a32ec507e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44848 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 z zI$_S?XO=fCpNuGPApdmZy6sHJXQn=6SxyJ<5|=8x@?wyY?m$ZIU)TubIj(^v14~1o z4HlVcM{|d?#NIKK*nT+C*`7B}?~K?{dWhZOGc+w81E(K^;Ui?o5>7jxVY8v)m39v! zEq^T=a`R+tBX}^Tm!V`+l zYD*WxOTAgLsrrUD?1hpCy7d!R4Zm-IJ;my!eX_pD<%xL)j$PR}-cuDPLt|sRbLd@6 z4#o=W3VKqgBwL_~|3p?v`0mmQSw|-bb!F{Yk=Hn+yuIdt_4DcYApiNs4}dq_{BL9V zf0c!imHq!33(J337MA~2Wm(nScKXjOo$m&_FDSmaHc?O}AVYA^r1j=uo%EBIOH!2u zHE2>nLrYB+jFx&EIDK^zNv8{>n*X zZv^@M;lJb2b?7)~vbT9Bc2DMTQ7k+W&z$E;A74TIXUV$al=Dv!Qb&~NNgwyYrs+@n zmK402w~{(uC^cw>Zt&7W|2_Vl1(E4q!>?d7mUDdjbAEk4^FR3xOms7g zPb{d#StF7l;f2Z~Pfl6qOiGOg^WRm}_#4BesLT!F6GR_p!=pd<{SBXH{*)lp(Wp0g z)*HNr>jm<4n{^(H^G+OjM$t>U=QfSDY5G&BbwH)4)m9#q0|YwDbLwu4^BT?U*C`)nAN0 z0pn2%SUO^sS=Wlt1jmn(Iz&R(aOl@@S`H zlFA(b_q7A!?yblg8ULeYt|rwjCF}Y z2@IR|q%PPHbl7o}oaNXgCthM!Tur=%<_3 z?y)1f@)%^n+VO~|RGRIA^G9@Bn)K2N>BiTwo6;5ze02fcW7;y7+F;FqYW1vs>vGqtfb0^$h7L zbMZ@~7lsd@O_4~xignoCwrR{8qGc%*XCW@OXtdF}{^YnaLT_e{QEEMH^v5x+;iB4p zuMln&*K>B|jI9u}G8#6s;wJFGd;&rYV75TV)cIOW#1w?gOG<-y(_JLu7ISZ)K5SRh zgfx5ed;TTy1Q=%c_G3Be7ZMKYGk7p7#%_3%vqdUampnetj%X)wQmF{jkx%$A(PKq0 zrzaE$FvNrcVH2A1R~60>>nrP?3ybGR9&3o8H4qZzhkU(4^}G zMDa}zhfG+f9t0wynPDb!0ZWk@OJf6@K)u>*uDW#H%pmZWhY*1YMB;R&LW#(4MDxi^ zV%tOdO9PHPle}+A0*-fW{Z8^IO*|>)7FdluJCyR27Pr;oV^ARSZ=i4MC~pV}g1l+q zgHBneu?<|_BEY!;lVX8_gy8!m#L(lj6sC> zHI3r8Jl>Mb!!~-r2p1+pVP8d%z3~I3;DlD_G7tG!v z5W=O=?|1_+RQilUec?=#NbVbR98br)eE!n{(ro^1ymi&vOkPF zB)Gfl#@*fB-Q8V+6C9G@4#C|e0RjY<;1Zlba1HM8ZOF+vx$m5N*L~|-|F`zqOwV+8 zO?6dQb(OYK~zh#kXyvH;RU7@5@4qKPH5;Lo}>+GUl57049pH{DlDfLF>Y`NA|)!# zHR3sAP)8rOSXsnAOt6{0pji%+hX8wbXT^(L3sGe`Qf_(r6k1#ft3F~ zWGXAAusPUEMKD+`c?z7yfeM`|Xx8-ySQ~GY{)VJUETCP zZCcWhxrX)y0>QTuJnUIC_;{m;{&#ug85A`i%t%-pa(mCE%3rC6xtR-i*j?uN(1+PB z*n;zqnbXv|=Qh;fh~r85%OO@MC2Y()$|B^ij4Azirn&BsDxw+ zK)BDL*nU?^%hEt9j-Fkt-hnXDF&Tr+63etYqR&-Lra;Cox%kq&J`e;BAqdq;)r#64 z2ByNxYPJA>Q{>H9wmhOXEvldf=+(&Ci?%Lp`}9WFB}|PKgmJ-HX^9Z${3z+VPkZelj0__ManAyHPdrd|;I@A> ztua|jgw|(H46O2(e!f3qr8z&AXncFdl9(R35Yud}!5&tLNvE*UW-WVBXRW2lsAL<3 z2Y)$MXhu9ar_ix?f7VMVJCs#X<|csQQ%J^U2Vt_BtDwwd>!^!pD_Y~i(tgDOjC(EG zKE?bk?tPADpOAWH4yHe|i&+1T)U*CqNWGnkp2IvNn(t`Uj|KbuwQH6}Lh9i{^~ph^ z7xCHz6NXf%QuA-E_u5w)P^pB~LV^zVTn@RmHWL{KVc|!wDtFiSI^P};8?Ey^G!EEw z0)JCxpe9!dPgfh_GRRCJStEtz#vUK}LNb+k@!e#WlWG`u9v0$;+X+b2oem9znXF7d z=Jlvno2*99Qa}_(>UU5N%ShBjEt*80V32qW|LP3*PV_9Znl};kNjQ7`qSn^*B5&Oc zPjOeS6D+1+vV>HwyDV&lRR%Iid)`10Y+ep6tjJeP00LiUezlTos7K+6+CFXE8!Gyw zKpCgAs|$4rXrsM#CE@hWLEKNHCt#Mr)~J3ZaMp%ogDSt;xZ~SIUFNy+o*adMxK^ML zW);C+iz=&ywNnbRt^3|G>-9M?iO56M<*?CL_G~zpAez-!M1vSv-Hr@W13~b?GEX-W zG4YSprk&)|^K+{savJtQB=m~Jj_&9WGTq-C)3>}drO8}Tk{${!nRH{V_b6BJWzch4 ztoJiza=?iPYf-#9+mwly1+N@G?KOjn2do@b=)_DgbiQRZ*`%_Y$BV)EJc}&IWBHY| z3iXHj`R8I4Fkc>V3;Zw8>6wE$OYSBi+g@57tWK|w8LXfpIR9(ayxTUQNg8fIT)3#`s~ zj<#N66q@o-jKOgZGg24cPVDq+#?q33&=RCnT7r_TjW+x+@cWFz+Y47qL-tSHh$DJ) zt%*yweMIlKlEL3$4gg*~fIBL`i2wU6{`K_6&h*#A+g}-Ss$Py}07WAUGk~0#sg;qi zgC~*B)1w_b6EhJ97qcE5K-s|+xI+^WBe0dTnY}9!%Tq2L@UoeUgPXI7nG0}ZCq-um z6BRR89RP6aCnA8VnWrnTpO~ksgvxVQre_0z1Bg2SyEAb-_XqCv1P}q911Y)?J=v5p z9Pkp5`zM2A;sjp!BZcq(f&)%NC)m|0LnitUm5P%ynu%%xhumxPY~eY=h^d6mErV=fRo=1=ukL*cN~A- zB-Roi=1%J0{pA{vp@QSjlUCr zc2K`+f1~&Z8Gte~6CCq17WW&)-x>NFyUz~ge@XG#&VTj!8^veC|5f{6^7w3*zxw>0 z;**Si)&7?hpY7;ZpTALjHmqN@|1HJ;D92|*_y>yrN!LujS?f`f>oqgQ-IM+lSZdq%cOTDk^;s;x!e z#!hZd$1?T-TY{%t~!4)=O3?gu!*h+#-BOjL|cAH8WHoIydzIq3PG zR_}k^Wa@d^{~?d(HRx%91x5z;z}+6L>@A4ce%gYFrIGVf2;o8mG$tW&qGypj`Htu1 zPR_{H*~(MrX+kp+(LW#bo-2fb!OC;2!oNS@jGo!wuI0)&lR%>F#lu(B7jcd`2OT-3_k+zc2R z0b?N@prr#xp!XNeXLJ99<`b1C2>{ep#AFmyXcdisdtX}FJJ1U|*qS~MNz}~6#M#Qx z)d9%=v#)w)@wo~ZKK(g17OvmM#>@oxH8^GtP9hed={ zCG}6=r`G@S0k#DOf$YH9@$8I#)v<6sIpL?zv(Pz#Hv)d)*qNU6^3?RH^xO@|3J37} ztK*-?KbUxG#|m`iPsb;Qo(QwCu|J>xHH4=UC$Q$Z6&w2>_jzjj)c2|OsfO{1ho8e@ zV}FV~|D0bxW%#?gfgb!v@EmIVvksVl zQvusww#UxMM#Rqe4-@{UIG^q54?+FB@~?lN>sdIS-5apxNjU#%&FqZq|6jmB+#KVn6&DcT-~^^Ea&Q6- zknw4`VrK`c4*0~u4s=paw4Rjo><^x1$rRO4|XJ%(7 z;sUCjgP8@m%Gw%PxDc_h!U2R_Or9_S;8oz`ypf}%*^?h6V&`Im13ca5sqU#O9N?#~ z6SB9k1wskH71-6xP93;L18d~0TwH*`!1EgRG)>?DntzaC|KpCI{Pz9&~)B#2SV}J?3#KF$a2w(~@1DFG4>JB^rr3A15SOP4)94*c4 z0agHOfGxldU=MHrIM|y39086`c!sT+x$Do;vkM0}0$sU->2KNqI0IY&E>@lZ7h5A2 zOMolD)zaC_4B+bF0B{3%06YO+)X#DR#%^Z7>HX|D{#s+6&;QWC-=n*KjYOD4enoq1 zjI3P0g?ovbu$n3w^KDENm)7X?Uv&=E(!VJ;X_o~w*rWF}N6{LhzhfhNdBL|YBODhW zA~>5IBKJ}>91ISQ!OgBg+D50suA*YdwRdDTRo;i;)7|6UR*+pL_M-*&sPDId_>2vn zm0Q0fuXfrF@i(0iV1Zp1AZCKCB+R=FY)XTM59wO_XrMf9Xt%YDVRaAtJXkbf-$M)+ zx0_4qd)}dcf=Q?72#H8hB$9+eCr}!vu8CCiYCXlP%H(%3@O67|SfSHyb}ex+90as; zRv|{HgotyG3KOD;Bq)s|6Tdqi%H$ifEKo*X$19bMNb2K)hJX%(IGt<-Pas|$*+Y{S zb9GhCJ;i(TafAULlffJDUME`JRXmUuJP2KBL?`2V?D3iwp-cabF6ss{J}zcJwFv_eb=5lX1RTD{lyv~Zo>-Xlqz)zS?d z?H)yC3HOh-!f&zL-@!EhG{!e#ao2f##AC{dARnInBP?Pt;?dKoFX{!JLR{UzaDGy& zB!330{X~XT8HJk?O6e+jaDj%t+>0=rKm3E+(^ zx@btPtRJN_btQ%zL5R%2I-ults`hUBhO56j=S>vX1h^nXcPzBb%fA|HriWDGsh*0)9${BOF_vf=-#p8Tn z7HM(H8Otx&2rU{rzLNVcB*Ib*(U2pg@OJ5jMb3K?Z5!(K3t~6+osd=~ocUrZefx*f z4Mnj%;vn8-MU8PM*OR;oN>1fYxy`mh?QT;JvYQvJ%v~Oj_4RbYQsib1(e{jLIOQNQ zkGZ6_4GW-ibXFm=fqZ4$J@S0y+aW4OAQ?0vnYNrgADf${i)hSqXd`egYXC>Bw=q)7i0zt zg#QQC@$(2Y(2>OX_m7C4m#dMn-s#^_A$-tWT}h6FxgyUFAjBG_TPWWQOhgGE8)z}2 zUE^USfRhFQVsiE@RB>2)c$=%f`|haCLpeg!e_iC%&{VW!$9y%ma*XXM`L>pDrJ044 zlbKeU;dqhu24#!lO{I-Z*&$f>!LnVQ#g&~d>PvlJRvfVbB5glV$Sz{P(Yjh_n$Rxz zQTcKE0kf=#gO3RG&=ep=(cKufXB^gWpS_?Cdj=3I^z8a@Y?!~(kRg(rOPXPtVoidg zLdLO(fW6qydko>JUXUQ-z0kPAL4#X;?Bq#+ z16)7$%2>Ewn^EG0V}!XN8r{hELOsdd0X}%FZBK`94jg6|V(dE;Y2VhSXvPLz39NX( zdXaDqkWtSOI|mq)9m2JRA_;rmGAG)|0kcI4!Fo9=N)_N-{JQDCa@J_OB12oq+4bD- zkh?0@GP@|$4)nc6K#8!s68BdE^J@_7PF!WUc^nt{C&nmD>aEl>LHjScL9WIusOca4LT@o@igiv8Z~W49sG(sjL6*b&FGwdc>K(# zhrneX)CEEr!=6c_Qh!J@KK{MM%DylpZ5mo~-i*xs%S^Dg$k)}O2l*Y~!N;b7OQIfY z8NnDJkltqjxE8|Ukne^0Qys=YG0iRck#x_vS6-ziA$6{LhU_DsVS(U{nk+;N$+kgy zlX?a~d`GQ_(X&7mbf9;WSbUK>5vt=zkpFS$40CNw1QI5 zb(17vPjb$Z+BT>mY`YiCaz)up@)cRiS+4cL3@DYTOSoMP~vL7Nh_%*m&s2|A% zG}641Xz?O%HmWYv7pW+w^v!YAqWcNl+Y*A?>_OOeiEP zy9fF791+*pCXNKInGI1WE+_vpi>bJ`@rcv|W5_(GPX=+`dBWRf?yM-zt_0FDi!$ z2DJK+q9o;P9XvLVsq;N(Eo<>g4{f*Y>?)6rtXmN6Q5CoSEat0(*H6pgq@;$cghNt% zlIoU`JBYWbLx%U2t+6z4R?`9-4pKsW+plrDw!#S$GYJnR8w*XfX;Qdi%FRZ&W3Vjk=ZmDd`>c0H6Q zgI3Nt*8avq+X*jUCSoQZ=H=_PcCCQgLu`5XA&zV}VRB?8OkHdyP)(q+z6(g*^Ma0h z6MLq2up=AEAr;jaf#)Yb)Mz$qmbw388;-yw!k19qg+v3PbXH~R?Seyrl)aa{Qygs; zwE_nEiLZ*$3xgB)SKQo=7~UO{aHL;1$jp0O(!=m9MX#RVu3f9U^ z5GPUF1A3~O6&&-q?4)Co9oIw)Ee_X^cdgReTBnag%p;%*wW5jQn7v>Wc%qx4WxTI; zGKt4|J{t$69}fs~7PduJl@K0ADAKnGs0^*seK#w6?-~g?wVnPBQS0(3O(w}1DVbWp zVD7NN5B%kA+x?kDA5Yxf0-5B3vYnUv1tmo12N~Nba(xDULS1q4NEg8rqoU)FJ3=3L zDLLBBHqG#svD4u2IZML#ubK0T1wHf)pm(v|kLnbOo1?NmZj>ky#5(EE0=d|C75m0vT-a^kPRwyAjygdE?~tF~z(<|0~!I)dBX$cSu-IfAl6 zU~j#oqAWe#_t=7@T;+9#cb3{u`#g+Rv|30!8Q<9>OlgX)V#rV%qhiP$y_rGOLoV&& zu4Ez9RH}Desj*iUfQr0$(X{DY=MJsz79!m`LPH214%~3qZ+X&Xe;a%6HUO)UWPfV~ z_8Zni+=$s5rEkS0g~f}?S|%kDS+&wjams3<{$XWswJ}yic-aH1Ef}R*!E~aKuh}Ge7mC5x#5za z*2<*bgy2^2#gG(jaXNj39Nb#0JIG0VV{_8aw`Vi&Fo7O$i;y0vfiaVk2IADTFly%Y zb~H(skFihkT=Me?;@sR>wdqCI{fhq4>r%hIV1He3$_|dz5JoCj5`W_twRzO1(;auF zzF>x9^zh1vf%I(~>FJ2}W8k3bzA56$gD9-KnaF>^|-kk!ru2w~%aXzaB#!<-b& z%$!_23~bZT4>h4=I1svBynT#p7-x3K{*k5Nz)r|VNe*o%f=jhM7T4^x1VxCMe6Vyh zXY;0BRk|#a8}7!FBKk~Pk`6*4otzi}8=;UF#n`!PO5bbrCY$)$e~Fzwp2+>~(hjvX zCeL1Ifx52dhlc!q@MLB`ySspC$>}*_BD4-tgZiux$MKSRcW60hj)tW1nG7-ngcg1e zs&Uqi0o(fJ9D`_Bq;S~|5fMSgh2AFq9wruLj9k<-9^-n!7-N5f_@y2fUTpls5l?=ZbdNIbRoio0*6Y;oyk)5o$ zZYbr>qN?&>v=s-cUdO5Q{?T#5TLGt~6y&pg<;$%;$2W5Hl!qZRrjHT#PIVVBf_FDX%_vP)D_CZTaX?F*SYY6i7U`(RWdlbZW+ zj*hS^5O-}h;xWNi*voKUs`(B#;?+o3YGO@2cq3e}57L5Nbsp30ZYZP5-e@DAK$twX zk$^uTMqH%ArXac%3H#>o3SR=@>#>XN#!-dIg@tOUdWGFv@ze+Rw}tzj0sL5|JLor_ zrWljg(Ie|oLC5Kx20jNVyQF@s&6%=fMoXcC>|soq9@_{T8nTHA zyEc&%DH;@4fD30{$1xT{a0v582BmQp!~vhEO^jGxbUl+h>M^YZHwPOpYjN&>Tzv)O$$;Qn)g<2Ivo&M>gcIzGBkD3B1f@NM7g1OVXt$v;pXw+2z6p1KbS{$fYc!|=-RTWDXASYJ} ziNm~j5vp9541Ev}h&cYD`C{>N=?S7-7QPI(Z+5x0WzN#K;(P^=GiXIc=k`tE;g)H7 z%8_H~a5^|rTY^O)Hy;hLulptEbY9?&5Z}P!co#X1MDXs{)wc#>tI{eH44|7jim*A1 zEBlY2&W9iHj*1 zO0OM{ALEIY#gSP*WI`6Q8Hh~yBAOF;s|mT8w+N>Uz|;NgLbe) zmkC)JSjPXs{1Hpntj*)&fZXC?(a8$6)N0av0~-e&JzoqZ$f?j};Q8U_GWE&?=b?{g zcgJtr>+k1~^+P+!U%9X;LSriT_!WLQ*;t~svtEbEpEXQ`HXpsVDa-g#XH(pN(lDYm8q-yt;`7vmi7ou z*7O`!lpLAYKRDGi&FQEb6A9=lSTNh6VR5kb=I!jv8Yj}?q=Q<*PPsn9q(4vu2)xe? zc9}zhJ77gk^n+FI_G#5bOWO6iRqh2zuj$lHc6k4>X&OEzA{3v30`PU;C>#WC6CICi z_d6?Xxt6Pri_aXa;47zIn}PHr&-MoU(V7KkE78dFiq6?i$KI^@(nIVK7Feu5LTwz3UQ+AWeQ zv>RynRgSw7ug%z>^cX3W(4`km>0i=ij+qIrJe1;?@WMiz>qOZS0#n! zojnx;HT?ovyhVZqO>M1<`#J?&NXv;kWkh#Wwi#oV@xEcXF&VQvGX|48OB|LD)`(dNj0+}z_ZN-d!&tx0xwisoL%I#&|`BcG!U0~f$N>kRmBS@u(pyth-s z>;>pvT}4SiylKV73~%Z6BD2mC$h1Ks^*2C+XUR*Q^!ebiwRj(F*d&} zBZwtz7_75ta*E;JT{xSVKL}0$wpiJ$c!^(+B%$t3o7m6X7nH~vFRrX${TV_!QQlaJ z<9pmJ&*cmZct_@~4cgpgOL-0RN^A;rIoqFRgO4BU=3S6T8J zFmrvIp-kvMz!sl>#cMoY_z^n`uC89FW~(L)89pEz=XXUk5ZB$PMG?~w>c|j?p){Nj zyQ@YmJxy*dY+MMCpAQ|--wr0;dw2U8ebxmJolQ}OV|ca1DQ{RZBJX3umpn)Hz}PX| zFFm{kiEILC#n|DMScXtlq~Fi6rmz#8UVMIt42G;a;{5Z)VjfH}>h)Qhv{o#g7oq}5wvdcO@aPU`=iY?cF1>S9QhWSOox8-f z@-?$?_Fk#I>+4KC`L(WX+(nAB?aS?&Q4pIldY&KN7;GHZ^lh!xf{CysRPN~0lYu1O zbo_Wi2c##Ccv~-*Mgbozky`M%cl?^Pj>l34&YP{m%-CLj+(*u@`?|1*#KC00N7B+y zK{V1?9jp4$pjT)1;j4_ttronMuF*!SY~j3A0YKo_CZO+bk->&q@u+u5h0o5m7bAIHy{%f#KXc7?$sJ zun{@M;kV&u@{ZibwsWuz0`ZJ#8%%{^6&W`Zar#cUFGlp?3~Ngv(~{|HiZ=Ze9+u+S zwzm;VEIS?{H~-Y^i$23rqT0g4x40{-v@bdt-HmOp(B8OsVL_ptE7O&5&5Z9^UgD1; zNiAN#1zYI3y)eoUK$l|c3FSFy$)u1ZC*7h{;?EI`w_~kVj{p?oF={UV! zN(4a!|HzWuxfY^&l$M;T3>}T43Cox91zi41Sb(C=(N}gnH1xp@ZN!({c`c0mW*x4Gy(N(x@F9)+O5c428?xlV)N#ug8^NPu3U0(wc|cK}j{W zZQw}DDk~ZZY!soGy$kgVUfw=ww&V8+P?%vQHK!y&%G2!p=2aw|UaGBk7i%f-?t|<3 z4PD2XxI*>Frbpw6!g~xHf46Ux!p-y2*X`^B-)F33)hnjESETXlw&}@e^^u7D)L-Z(loF7J?S1cC5AT7ntQK50J z1j|~#SK1TG=hSlI`dwh?YF_IxDQYq|fCC?1KZrQG?nHIGI!D?LxFZnNV;EJHu9y!4 z5jy_1>Dg5~#LW5Vu%n05z=53~;S+nN5hQpvl=`VMb#FP}Y zPf)i*-H3{soG`#pIyGcVBIt)_Lu5Ti_#qAj)mK=Fsf@R%YNQl^@*QS~S1oXJwb9@) z*21!!J&m3MRf$M#M>Sxll+R7RI^Mkv+P9lNFJ*(;i@HUBp{)*t(XFBV{uOlE;twu?#~$z1lP+M#Ho%8^qapq4sv@XUVNAH&*CN z@+$+okwfrY*ybR;cLPegm?+^`!KA}<<&C5 zUo5J&xVq!N)Ot%kd!cNPqR;nvjrBo|{y;`o5yH$nZ9{!c=wLO=Q4c2E-f|Fue{Uhw z!j7k&sY;Of6e^}`ZOV0QGOGalO`DX;kiTAp(C&_I<$SU-*;ob3OA2h8prti7RjhIx z8#e#(CD^i53~6%`ACgDY$797U)!t+Hp`gVvYh&NgDzD}FiWriotcRcr7oxfuhPDxAB z7caxmW0{k_IR=q#beo6D3C3b!RaI5PIk`MmKe(Wd#dn|m#KzD99?tFI)rMYL;q3=$ zR%>3vj02~0E6^UH`PI{EN~dHh^pgz-2ysH=CAUQ*S=)?|%jeUy@8gsdsTK8WS5Usa zcIGXB4>x>v60 zZ|LLl*C?Kd3wTuF^_S2KKAtLhOTo$Z$qYSgJH233ot(<468H#>Q;iot>@#LUC&Uu9 z3j#ymX7zGqrqgyN=b=;@d(EHNMReYk$2oT-G&ifGd7#l3ke>U9jJRXHmUQ#z`4r>C z+w2*F{UO$wKT?Q85uqucgv%mZ7o_{4^I@{$!rda|vBhz0{Lt61X$+G%zr^;BBG)!R(3LV^eBWwGga=c%Ke}#5AK)H=A z2r!{CT3soL;Z=h20Hc^*I)UfXa{y<9FaAImc|HwB^ci-y!CGn$hDinX}o`!_oH;1YqH2nVHt z5nls&_C94ERgA>>YYR{hd#gm4PhU*L)iO6|*2$bhWl<;ZMY;7d-$Cg#>BttW zD=!S8z=-8)l7ZYHC+C(-grrN;UShiukkT_7VHI*i_l@dW-Ta`r3Hvm|_l@AHXwzm# z%)>Iq;gNZh$D5S*npBE{IdWzU*QiIijB6;vs#h)!IgTxF2!{v;dGBrFGK_-e0e<>{ zSpE!R41}j-GT&KCF$(kqvU{jx(UQ&O<@D5oaKKWktp7XXa-FtT*~9XojRn#B$Z96x zJst+Wc$YDNy#t@nFxx40R;uw_oYc%Gt;2Bs`Pa=pYtEw{cTnVdiweOv_Gfe3U5hzA zaz{u)KjMbnN3rZH-(jsM@wtjE)Mpu2ebL)b7`JwG@bZ2*jPA^=Ch&3D@9489e9NzI z9;;lSG!_I>&mfn1Q(^p$Mk9fedNh>I_C5^yWqfS7+eRI~*2;VR<=BDNi_(`N+l$t% zfxxXeqno+m5w2kVwEzWMaA}<4sD+BdP$LS% z@Wzcd8ZIv?mr(TbRbLZnz%^ep&1+(b>`{dRWj8Pt>;zQu#}PPhDGxc+N8a3uw7U4l zAh|SdvE_@q^$K1iqt|PKxvf~)0{3xTy2x3vFZ#p~4JKHb!J{wzN~c!}1K;af*O;dI zfk07?vl9d*L1sKS441QO6Bf)BuxI*+6M9L$;q!EX!eF;Zxk$B7A3A(96=HV~;OoTd zGaNUKi*YhJXO8HdA-%Kc5wrF(qdUqyDgD62I1w)aYZq>z)sB6 zMZ+h72``k9jtY8I)o92(zAcw}UX}6OC~w1F*NIb)s%9#VFZ5WZ}Qr9bB)x|Ov%>3Q*3l? z6ot}O6~bPcMvaWHvJHyB(s;W+nPMqjALf&Ckm8Iuh0iq`x3ToXW|dy)BugZVF`ilLRqif?;WoMGSY7S6NfFYh zw5#+z_UVY*Rg&YL0v7{0cMWvB%_ZC&pRD`ioxYD6bJ>E~bR^PM;9A)0@@-#0tDb6IO%us&xzcMy--Cn%)-@YPU43)YsDRt`k zIB{&}Pg~Zx5Xa2{rO|-`rmskk*`E5C<~S;&V05~%YAJ+;4^szCaAkTJ;IhmM_1zyN zdKt3j?{M5xuHJux#{K(@;h$g}@Yh)M%)orr=M-2DX3l?1kmUSVFpleYFpd+5)ctdU zB-4LRkYopv`3;PFN|6)=LUQ5&NgymI4UhrI{zJl~20#;_1qAAh?10IRE=KmIzywNT zXCo6EGuP*A$Un+I^C6!yD{UR@f6K3YPVoeo*_l42Lp~*2{*iBK`;RG?Hhp2E0n^mj_RqpIYtOm%z^gxb`z!PQXOgCwJ221l-=%8)fiD8Q0p4cL z4!`GYvOOo<{{}PuhSL7`Ih!1uOdP+#j1}I%oXxK@7g8q9@@2W?d~qrXigx&=74zB^ zr_s5bQ7~&D%%i8W0WXE)G9kc1xI(zT1P3rjVuW$)l+BbiDOcFp**N&vEciNetUSKD z6}0ntT)5?1etgV2=mOu$_%u3i^U0>-a!G=K=@2rg@4MXm4)Qwk1|iDL%;A{fo0o?Z zvNK72^1gwYy#kTikMB%jQ37CJF&bq!?e2Tcl=lt&SR}*ZN&R-}>6Es1{@&;q`Jv5E z>7p*vqvcB~kH_+n1_py(^VBlS!yNuC;_|zPHsTAGV*t~#(0ilL%fw1U2VcJz1qa=| znZJeV3A+}X_wn@d@^PBH@PhDyp69uOz7Bi+x_5R|U!d05sUNl*A*v3Rd0x5S z+#Fo2pjLB?aakHv%Pg;vA1N3#+isRG&bc6c@iiiN{HEhDYEWJMEz<+@lf=u(2>fnk zW2l;VP4QOweUfD&cT|=LzHT~Wz^d#Q;tOO46ozhHV}Y936p0Tgdl5}A9LC_s>`no* zl3ytC!XdjUjEQSf9m$r-8(&6+S9JS?pw^_!iqjD{q8_2vgdh@AUfCy8^&Xao@`Q4?{7T&`9z%XGrPbtQCmFoL zYo_CdWn6zePlJ0W5%~7xLFMhR5^fadJFkej;YHtufs10h>8a!*afSOTtFpprx!bA3 z(52D1OERT61|NyroUb#VHo1Iv&t`TA<^5Ujx3F=|r-rw^e0%r$mQ&7qiOTA06R73J zs)92e)@n}acy+q6dG~)8m&%O%|ZtWSWmb%|fh%>Sq?g z!$mg87Rf6L#EUK{l6yl!i8W9r_F`k5X{WHa>Sz^M!&=S{b!fa5n1Ah@2*;*KoeJ}q zFlA}RY0(F}|5le5gmc6Wjv)k2q~?8b^XowQ?Tl|=ZF(TJLIpRR7KP~WiHS;j`V?3B zkh?rVdlm1$;ijB$gb~__Myg&Fn6bo=NrS`*;^`wxxq8Yo&Xw*De~Al5{~`$k`)VRD zo~3iLTPfetyY#~QW8oKe!u4P{~Fqx80F^1Pk2^4r^@uq4#gDtKXd$jekk4%H!H@ zkZ>W6(Yxye{E)Nc*@8`@hzgc)>_}YN^o8~K+c%Co z-XS>dka87vS}48d874<&xQU{jI3beY!g#~iB=p?9D`BFcGluqYH9fbT;E)B93dxoTr8iYpl7xX1$x-FsT;CT1uP^-*A6hRBpYHL6A zW;M$0uc_U2HnpE%wk>c9!L$KGPs>(c z;{y^M*ioPDg>dIEPa(Le%zL6Mq%>HS!xi>M{iZtOc9G$8#(T1%7Cf8U2WKpIfqG;< zrs}FmyG|w1HvtC7zHb*MFR^H*JwbllYkK3|A&$57-&~1%afJHBv~`2LZtBKo`y>z~ zgSI~EA5KNMQlBr{QeXqI5|>-jz7azO!yu;4N;NnFpsTRiqr(N6`nrX0k>ixUV({VX zs+;_LwsQ6;SaOoP~8I-9+nwvVv{@&Wcxs%4GF)NG*lstr7G?=xLM?{)juc59cN1Q<#{Fp(r~Wl{Mo zOI{mqm;C-l18<1hhg{hfVNytU!$Mxc2Ag`$m{eWJFT1#<{ue~Fq@N*ueXM+R+h*x4 z{Wp-ikUK&^+Rw=5P%MtsM?oa2!-d&BFuMje3ba1Hc2`)1z#)?e4I>wm&Rc&M;O%i+ zB$mqM|J;sM#*bfwTMzvH}hU(E5%wc0m?U8 zMVgj-U~3J;-f-;i%Xw!d+4}O2XF%U@ZzR}6cNz6vcPfNh~nTU~z!uU*Vn)Gc!KT(6>MOp2r(io}B5F6=@+`t-3(hkYt#p6CxO!=<~JU)omERLVodn>B^ zo-%x<+nQ?o$19g?4ra!<^68`iq<#OAYVhDf_1B;ezJp;5=ljg@=PRK`G`*f2@R|-c z2C4lhD58{M;$p8up(uPn1zx6QYbNQEIDk-6&0bP|F@uC<-wlpNM*n;uW#M>r;Sn60 zJHK0o*-a#xS?pR=X>6@}S2WcR=NGu}J>Pp|=@nMD{`*Ibd&3_6wqu&? z+{k1>p2JA?9~Em=)N)4>R}bM)HjJo06I4a02rCPJT9No}RK%GlsTCd};ioSjQD{KR z9`C~F6w&oPpx4gUyRK9-G4mZ^;G~~vlA&NRfNcuI&d=AV4yq&B@coC}rhd!LL`Z%? zhGcp<&v<}emx74Tj=?prJb|8iCX8J8kxI2YfKE@3PDUEstzJ4WhDQz6$076EOCiF7rS6VcW9MU#)v0U;&JG(kI6r?yQRD`kqZ5g z*Ff6Jc7SFW8<>`HvUVhZk!@-F@rAweTWyy|Hjk#OAC4`bd>|J30!e~vx-Bbt)aPM~ zS5?yY$3NiHVz!jqm1B{UrNn9$-px}1lM{`PqthYDjkTP_lEJNiEK3VQQc%zB`t_@% z+lleu_DM>Q9G8oCq0%U(td**lZdkL$Ba^%t?%*ZoQEQfr?OnJDDrOpShilN^_#6oB z>gr={_UcjngYf^?+L^~g)wh3~%91Q4*<}h1GG;Nuj0VXPX@n5TGR$DI%ot;dB!pWc zkq8kHWyzW?A*8aDWXYa2*>_6(&UCMMUccx0<34|Qo%x*WyI1PRT37{eb=jtq!f~4BY}+b zyJ^vq?-*PU36q_CS-A?X4TeJ-E@!&gI=3CFOdGhFXXHSU=X-k+v3pqB)K*a5*=`b~ z!!>_dd8|NgKtgbl;4xZsID5WfWe-bLVu?tf5Z4dKJu?PxmgBF?wpDi%>zK>uUl&>@ zb)LKry~ncd#`SPD#&5wg;cI9Z>T)l)W%`ZFNng%N zrPva7|771*km=&g8ZjCl{EE2w z+71~C#+P2a;rb+ycri<3WRlT+xA{3|L#E6MjC5+X&X9!Bk2Wa*PQ!}afs4ka@E^QZ z1MK*-Cr=s1s$2|QuickEVZ(IJ&5M#ygL^=wac6uo9$6gsuB(2vdT3Wm-0E4bwM%A% zxSQ(Tdd>dEOq4pKJ9*WR#&oZHd{s` zEXIMq-5)Q=F92=knGC1KLiabdF2~rjIl8)>fYdX%ztfK|vE0aD)_miueOiC~%`F$J zP-&dtp>NXwuvDP3)sBK4e(-Wp!#fz6uVIjQ3B)vBg1olwKoah#8C{wEf^5+Ax~<8) zO!XR5;i}h<Fx*Yoq;jpr zY|g26*p@sFsaL$FuESwg@rYnD?8w;cmi*HNM=kg!!(_+yEMTZ?VlD0{?y%%TQ0cO~ z;Fznr;5e!HlaiHCEMvmW2M!e{md!cJIJ!=nIj85zSH6JhoSX6wDGZf1mKhFzw6Y*%(CgaUlc6Pw~96Z6J$)6?J*Q)N@ z%VPID8jvm#4pJ2*aMekkiX2d_X;T3m9}espeZ<#twQ$#7$`a@G?w4L{{V`TSRhXY_ zGh=w=^{zqH`r*f4Q$hPzCDcz(Qh9>+XaT_AcL6k3ZuO{+f;|~am^8QJ31>$WPRZZ* zf3Ky*8~6T`;0WBvoylwRqbRIJ#Qp}jyS|o1=4T&s=r>RUPnkrqY^H$g>A|dt7lGXm zc4#Yj~)U5c?HK<8e*1 zn)3ZHKv8nKo`3tLbC79Mdsxz>P>^3uT)BKo(r51Wn>o{sGACQ*e7^bY>tS%^pFFpG ztLGs9AoKHpBBdYXv}c{Nx;h40@Q71kAwF+Id+LtfO-P(PxcJTgw65Nsu~&2bCo^wz zu{##3h2D_8!&DSlx`sN$?ep9?KANaE0f*fVI8S`w){8qNGQb0q+Sl43RXD`%lWq5Y z5OO&9xsJLDSsCd$rfaq$p*{1P90yZ<%JUb+))Tal-^>e#hO?*Rn!^pWwR23pMf5g1 z_Ts~doJ!)t4qRZn40cb*3W=IgQ|i4Tr;to`#VYrD_yv}2#(UT5rROhoUI*VzpsX>? zXN#WP=q~Y64mz=ESgx*OX)R1pNz+i-6CBJE{OLwVTU-05`!$Wpu|&h##N1BW+|!^h zX?W%G;Ox}uCt0>N<0E0g?B02V_<-MvBf`v*$>y=Cm<;e-$fE9Loy#~w+*wst-i&=6 zj`#Dfj^ybEntwM^eW-Wvb~%k1opG}nO*=N2wJ4+e)a}D}@T%ssLa9Q{!H!}5-(DXQ z%ZwDm4RE5a&aIEtcYTbyJQc@1A4NOzz1RA-KN{QK}uMxSqA0oP7u0A-NkGUs~ zwXc+^+%pwiP2ku^aj4{Ug~%5+TOMQz*Ar_eKc{%yAXS+bsH%nVI({U~w0rqM&IZ6HWFO}m#jRrt zAhK*yk3W5HIe1?z+Bfo4Wnd|DY+jJ(V%ATr&XE%ahMZxNKe`oFB?R`KIt6uCN|Ft&StvGGu!`!mk>Lh$|o(dwo7>BPRio81iaPg>3n zD2a@2-fmuXZQQ)WXJUGlaI8W2AXodvzS>2Wit8%}0$G|r@+FEi#ALGPzp`SU7M^o7 zF(0@v*~re?Aj^Y9^#)9IrVYMpU8_50u2d|fE;*!n_n3N(WG<8&Rl>+Fef(1(2^7Le zdN+JaywFYD5m`CScAEs?ish*oBm&-P;?7JiJx;wj% z$Fr`Woe`!CGUQGAnrpN!Aa!x>M{=J^WUd`woaa4Ofd@ue$3GG#*h`m6i)JCuHL?^0 z=cNn765cZm z7Ny&-bkr7@*b)5{Mfv&l@NY8P+`}LtS#xpJfn-xukaR&lXG0j)k~v&dD&wj-4Akh* zm@Pd~$Jiqq1by@@uCFDn7yE7`1w+FDo^vY0X=!%peUR4|gz zBX4h0q{T&?D@O%o-1BgX&3aH4NNg3sIW0*Ev;-xa%~7LJuD%=3o)e-+ zV$Mj%d1rpF;t#N!*^E{oJX}ciw?WrpJQ*mrLNDOqzUW;SPkoGYv?$aW9O}u5F%Qjy7b?aSo zQh9vz_5j_lg<*B<#cFW;9!$1N^=x3(`AqCCEb#>kqzSXm#6cT*}Zn@h-lW}hBZ#R)rU zK0fi%rC_G2toMM08Fn(uByuU3+IKEXrI&TZp^$;=HNVr%kdW}Og7XnL`$~qx3GU=J8eYj35-Oh(HEF$iLpfbi|Bz&;+`jee;91<>Ii=a=m=olwwfxL#6Gy~@ zuP6}~rB4F=kDc&vYC?RxySO&duPTZ$@ruRBkA#4fp&GSy>=4(k3v6NDCBosASDp_B z2)U=I1vmF`P8Ohc1sEqS&8DCqDWWl^cNq8;2FwdfHhZFPDpL;dWG)~=$&wS%^@x*2 z&9N7Pm*3WX0Wp_cmTJ)!Uq~*GSvsN0nD5R7{NBWt;bGkCef4?DRE_f6x8<~+h!;$S zdfk^sy{=S-&!S&tB*s$f63DLlnK;HukE?wXOIZ8j}(ImC$XIEc*QeE3` zb}yz%JG^yQZO55&1v@XipET>tFKwAkgMMgYh$MWf!0*C%7ZSOh6qe)22Nb%C3^TA>zy!8gsbSa%1dG$jjt5 ze`#!fwPaJ<1QUv2`@G7GpE+eoirF+VpLHLE<6i!fq0rmWD5uod?9#K*$IM+UEc}vB zS?SogS$nle$h-|* zh`wc?7-g{@a902ux$C0>Sk4wY}nPxF_wJ>=dEBvBb!;5DPmRDFW0&t&PDYaODRK*UjN zv1lH@6J5uA+U&pWxz-o}fkot0K7GUckQ?7Q>KJ%E^EUbsc+-?r`+=a7`}4#Nu}{8A z`xE%6#PYhMm%p@e)KFiPayMuSHd*@V7(22d z<}dnlxKmjC^hV!Ivv2DHOU8|tPAipnD3Ai>M#BB@y~?NayK?da3RPLh3k1WM(*+)N zygMo(HYZNe#<>|!3;awiKhM(74C;Tr-|pzKw<*tex$XNptQ&uc=IusWvx>l1f}#qF zSIMjv``@^T@_XH@|C#!JBPrE<*d%G=8z=(RTQo#g&tsQMr`H+|UAVaccpyIOT+ zPVjb-*7akQ?$D_l7vk{EMh>fA&llIrr-+6Zu$8IW3%?`3?8LIhHl#0OvOkX(9#Jw1 zaC444Mzqw`^d_0QL#)(q&#X+D&Awi4B8x7{$g}7iJ)Rovl3w$%cBI?YXDKIr@LX!K zpZ7rKG*^zi$Gt>`iignW4aJJD_@gJ{f+gB2_AM!mS@;w#3lEYNc{~QL_huA->5l0v zLigd&Ubqi;EY$o(p1gH_>hvgSL126 zYkkx^gBQQc%1Ha5{AT*>Ti$0JYT06^7ar~TKnv0IJH^lHE9kV?JDWa%T~2$ys#m-5 zAc!^^AsFMxkY7+AjtT>L@H{EKD7JCX#uYbuq)4uFAE!e*WmqfugJXvDr+l1eb|yXiLZ1FJ z>)}rr>fbOT6WrN9NknitH0-bcYGYMADZkPLK-NS%lCu(cro0jiA`z6p7f?7Dj-p1i zCuw<6iRZm^4Q;#}Y%m0{iZUBk1rI=-i4adb1!7Bb1Xy{lAOH=ebX3jYtmaX=fv2LU z6U7N&vVuIF9GzViJ(a+}iYNm2bQuZ;{W76BD1l9IdLSB^?C3zEfe^A7SvUkPCj+vj z0u(C`GSvYDmz4(tRZe-T(3CO@SYH7S23WyUmYQt{8h}^RrXh(WC73=lw<;h%fg_4HuNV^i$rz?(Hq8F zlig@aU?SQEg@hsHAV>m24g!Z0@eqJf34;(2L~D6C+8TkE!~EG2S35Zc^N+j=v&@U;`yO66rm11)Kp6^pjwtXiKI#;Q_zLQz!t| z5+IubX+wb1f|aqrLmCN4E>iv#m#U7m-)|fNmWY$1q9fkfP6_M@ArNixZjLmtGTF(Q zM5nCb39`WA{=Nu~B<0_4ewBv)UE_aPqF)ja{lIEL|JqxW*+Bo&_3u^m_l63fbCtjz z^zCv7M3>IU{bRrWGyEn0Q}jy#sbKVo0;ZiFQUb5=vIxstph1sTkPOyG(F90iw1n41B$n5a107ycy7^vX+!}?%dHv$U>9!F zfUeNrP~B<=R{$WD+cY$ij-K9ThXCH_-KHThbkz4&JD38HXt+%SR(Xd8gJX7%13?FU zZ>bNCfzbiFTQs03!1Uav0l3c{Z6MG9lyj>c0!D{-Zr9}K983E3*Sf(maE0yl!B7Z* zMY`1vhDPt`9|9(~qbvf3+%X4mj2xZhzolKEK03I3iv|P-fUMoB0rk;;P}*V#Xz1-4 z;4T37b*mjvAA0*Z;3zpdjB{IkC_3_dyGF;SZqeYFUr5!h8Vc~X?RIGRj(G-#MnAh^ zOIbjpV=1?2fVa?L`&%_MoDNXmrqM~TTQvks0r&>HL)&R5CkOCmx7nc;cKE%V9A?Kn zBjE5IK8b+K@AL!Uo%roOi3EcGA9G5h;sI1Al?{spLC=%Ch`^o$0uDJL14okpJFNi- zs_kq`1_1*HP9A`2tAot2FjX~xcq^}tR70yH5U14C&~P<5IZcEbu(fI+HRYB6yM;OZ akOEg4o=W?*(IMqf3P?5y35|1_Z2t$DW?wG= diff --git a/docs/doxygen/other/omnithread.ps b/docs/doxygen/other/omnithread.ps deleted file mode 100644 index 9e858f0b..00000000 --- a/docs/doxygen/other/omnithread.ps +++ /dev/null @@ -1,730 +0,0 @@ -%!PS-Adobe-2.0 -%%Creator: dvipsk 5.86 p1.5d Copyright 1996-2001 ASCII Corp.(www-ptex@ascii.co.jp) -%%based on dvipsk 5.86 Copyright 1999 Radical Eye Software (www.radicaleye.com) -%%Title: omnithread.dvi -%%Pages: 7 -%%PageOrder: Ascend -%%BoundingBox: 0 0 596 842 -%%DocumentFonts: Palatino-Roman Palatino-Italic Palatino-Bold Courier -%%EndComments -%DVIPSWebPage: (www.radicaleye.com) -%DVIPSCommandLine: dvips omnithread -%DVIPSParameters: dpi=600, compressed -%DVIPSSource: TeX output 2002.08.15:1756 -%%BeginProcSet: texc.pro -%! -/TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S -N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 -mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 -0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ -landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize -mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ -matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round -exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ -statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] -N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin -/FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array -/BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 -array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N -df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A -definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get -}B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} -B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr -1 add N}if}B/id 0 N/rw 0 N/rc 0 N/gp 0 N/cp 0 N/G 0 N/CharBuilder{save 3 -1 roll S A/base get 2 index get S/BitMaps get S get/Cd X pop/ctr 0 N Cdx -0 Cx Cy Ch sub Cx Cw add Cy setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx -sub Cy .1 sub]/id Ci N/rw Cw 7 add 8 idiv string N/rc 0 N/gp 0 N/cp 0 N{ -rc 0 ne{rc 1 sub/rc X rw}{G}ifelse}imagemask restore}B/G{{id gp get/gp -gp 1 add N A 18 mod S 18 idiv pl S get exec}loop}B/adv{cp add/cp X}B -/chg{rw cp id gp 4 index getinterval putinterval A gp add/gp X adv}B/nd{ -/cp 0 N rw exit}B/lsh{rw cp 2 copy get A 0 eq{pop 1}{A 255 eq{pop 254}{ -A A add 255 and S 1 and or}ifelse}ifelse put 1 adv}B/rsh{rw cp 2 copy -get A 0 eq{pop 128}{A 255 eq{pop 127}{A 2 idiv S 128 and or}ifelse} -ifelse put 1 adv}B/clr{rw cp 2 index string putinterval adv}B/set{rw cp -fillstr 0 4 index getinterval putinterval adv}B/fillstr 18 string 0 1 17 -{2 copy 255 put pop}for N/pl[{adv 1 chg}{adv 1 chg nd}{1 add chg}{1 add -chg nd}{adv lsh}{adv lsh nd}{adv rsh}{adv rsh nd}{1 add adv}{/rc X nd}{ -1 add set}{1 add clr}{adv 2 chg}{adv 2 chg nd}{pop nd}]A{bind pop} -forall N/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn -/BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put -}if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ -bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A -mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ -SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ -userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X -1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 -index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N -/dir 0 def/dyy{/dir 0 def}B/dyt{/dir 1 def}B/dty{/dir 2 def}B/dtt{/dir 3 -def}B/p{dir 2 eq{-90 rotate show 90 rotate}{dir 3 eq{-90 rotate show 90 -rotate}{show}ifelse}ifelse}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 -N/Ry 0 N/V{}B/RV/v{/Ry X/Rx X V}B statusdict begin/product where{pop -false[(Display)(NeXT)(LaserWriter 16/600)]{A length product length le{A -length product exch 0 exch getinterval eq{pop true exit}if}{pop}ifelse} -forall}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{ -BDot}imagemask grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat -{BDot}imagemask grestore}}ifelse B/QV{gsave newpath transform round exch -round exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 -rlineto fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B -/M{S p delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M} -B/g{0 M}B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p --3 w}B/n{p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{ -0 S rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end - -%%EndProcSet -%%BeginProcSet: 8r.enc -% @@psencodingfile@{ -% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", -% version = "0.6", -% date = "1 July 1998", -% filename = "8r.enc", -% email = "tex-fonts@@tug.org", -% docstring = "Encoding for TrueType or Type 1 fonts -% to be used with TeX." -% @} -% -% Idea is to have all the characters normally included in Type 1 fonts -% available for typesetting. This is effectively the characters in Adobe -% Standard Encoding + ISO Latin 1 + extra characters from Lucida. -% -% Character code assignments were made as follows: -% -% (1) the Windows ANSI characters are almost all in their Windows ANSI -% positions, because some Windows users cannot easily reencode the -% fonts, and it makes no difference on other systems. The only Windows -% ANSI characters not available are those that make no sense for -% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen -% (173). quotesingle and grave are moved just because it's such an -% irritation not having them in TeX positions. -% -% (2) Remaining characters are assigned arbitrarily to the lower part -% of the range, avoiding 0, 10 and 13 in case we meet dumb software. -% -% (3) Y&Y Lucida Bright includes some extra text characters; in the -% hopes that other PostScript fonts, perhaps created for public -% consumption, will include them, they are included starting at 0x12. -% -% (4) Remaining positions left undefined are for use in (hopefully) -% upward-compatible revisions, if someday more characters are generally -% available. -% -% (5) hyphen appears twice for compatibility with both -% ASCII and Windows. -% -/TeXBase1Encoding [ -% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) - /.notdef /dotaccent /fi /fl - /fraction /hungarumlaut /Lslash /lslash - /ogonek /ring /.notdef - /breve /minus /.notdef -% These are the only two remaining unencoded characters, so may as -% well include them. - /Zcaron /zcaron -% 0x10 - /caron /dotlessi -% (unusual TeX characters available in, e.g., Lucida Bright) - /dotlessj /ff /ffi /ffl - /.notdef /.notdef /.notdef /.notdef - /.notdef /.notdef /.notdef /.notdef - % very contentious; it's so painful not having quoteleft and quoteright - % at 96 and 145 that we move the things normally found there to here. - /grave /quotesingle -% 0x20 (ASCII begins) - /space /exclam /quotedbl /numbersign - /dollar /percent /ampersand /quoteright - /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash -% 0x30 - /zero /one /two /three /four /five /six /seven - /eight /nine /colon /semicolon /less /equal /greater /question -% 0x40 - /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O -% 0x50 - /P /Q /R /S /T /U /V /W - /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore -% 0x60 - /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o -% 0x70 - /p /q /r /s /t /u /v /w - /x /y /z /braceleft /bar /braceright /asciitilde - /.notdef % rubout; ASCII ends -% 0x80 - /.notdef /.notdef /quotesinglbase /florin - /quotedblbase /ellipsis /dagger /daggerdbl - /circumflex /perthousand /Scaron /guilsinglleft - /OE /.notdef /.notdef /.notdef -% 0x90 - /.notdef /.notdef /.notdef /quotedblleft - /quotedblright /bullet /endash /emdash - /tilde /trademark /scaron /guilsinglright - /oe /.notdef /.notdef /Ydieresis -% 0xA0 - /.notdef % nobreakspace - /exclamdown /cent /sterling - /currency /yen /brokenbar /section - /dieresis /copyright /ordfeminine /guillemotleft - /logicalnot - /hyphen % Y&Y (also at 45); Windows' softhyphen - /registered - /macron -% 0xD0 - /degree /plusminus /twosuperior /threesuperior - /acute /mu /paragraph /periodcentered - /cedilla /onesuperior /ordmasculine /guillemotright - /onequarter /onehalf /threequarters /questiondown -% 0xC0 - /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla - /Egrave /Eacute /Ecircumflex /Edieresis - /Igrave /Iacute /Icircumflex /Idieresis -% 0xD0 - /Eth /Ntilde /Ograve /Oacute - /Ocircumflex /Otilde /Odieresis /multiply - /Oslash /Ugrave /Uacute /Ucircumflex - /Udieresis /Yacute /Thorn /germandbls -% 0xE0 - /agrave /aacute /acircumflex /atilde - /adieresis /aring /ae /ccedilla - /egrave /eacute /ecircumflex /edieresis - /igrave /iacute /icircumflex /idieresis -% 0xF0 - /eth /ntilde /ograve /oacute - /ocircumflex /otilde /odieresis /divide - /oslash /ugrave /uacute /ucircumflex - /udieresis /yacute /thorn /ydieresis -] def - -%%EndProcSet -%%BeginProcSet: texps.pro -%! -TeXDict begin/rf{findfont dup length 1 add dict begin{1 index/FID ne 2 -index/UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll -exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics -exch def dict begin 0 1 255{exch dup type/integertype ne{pop pop 1 sub -dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} -ifelse}for Metrics/Metrics currentdict end def[2 index currentdict end -definefont 3 -1 roll makefont/setfont cvx]cvx def}def/ObliqueSlant{dup -sin S cos div neg}B/SlantFont{4 index mul add}def/ExtendFont{3 -1 roll -mul exch}def/ReEncodeFont{CharStrings rcheck{/Encoding false def dup[ -exch{dup CharStrings exch known not{pop/.notdef/Encoding true def}if} -forall Encoding{]exch pop}{cleartomark}ifelse}if/Encoding exch def}def -end - -%%EndProcSet -TeXDict begin 39158280 55380996 1000 600 600 (omnithread.dvi) -@start /Fa 134[ 45 45 66 1[ 51 30 35 35 1[ 45 40 51 71 -25 2[ 25 45 45 25 35 45 37 42 40 8[ 66 3[ 56 51 2[ 56 -71 5[ 30 3[ 56 3[ 66 23[ 30 30 40[{ TeXBase1Encoding ReEncodeFont} 31 -90.9091 /Palatino-Italic rf /Fb 134[ 51 1[ 76 1[ 56 30 -40 35 2[ 51 56 81 30 2[ 30 56 51 35 45 56 40 56 45 14[ 66 -2[ 76 5[ 35 6[ 61 19[ 23 30 23 4[ 25 39[{ TeXBase1Encoding ReEncodeFont} -27 90.9091 /Palatino-Bold rf /Fc 135[ 50 83 1[ 61 33 -44 39 1[ 61 55 61 89 33 2[ 33 61 55 1[ 50 61 44 61 50 -10[ 78 8[ 100 9[ 72 12[ 50 1[ 50 50 50 50 2[ 25 4[ 33 -33 40[{ TeXBase1Encoding ReEncodeFont} 30 99.6264 /Palatino-Bold -rf /Fd 134[ 55 55 55 55 55 55 55 55 55 55 55 55 55 55 -55 55 55 55 55 55 55 55 55 55 55 1[ 55 5[ 55 55 55 55 -55 55 55 55 1[ 55 55 55 55 55 55 1[ 55 55 55 55 55 55 -55 55 55 3[ 55 2[ 55 1[ 55 1[ 55 55 55 55 55 55 55 1[ 55 -55 55 1[ 55 55 55 40[{ TeXBase1Encoding ReEncodeFont} 65 -90.9091 /Courier rf /Fe 141[ 36 12[ 44 56 2[ 45 7[ 61 -61 91 1[ 71 56 48 61 2[ 71 76 3[ 30 31 76 1[ 51 56 70 -64 56 71 10[ 45 3[ 45 45 1[ 55 23 4[ 30 30 40[{ -.167 SlantFont TeXBase1Encoding ReEncodeFont} 29 90.9091 -/Palatino-Roman rf -%DVIPSBitmapFont: Ff cmsy10 10.95 1 -/Ff 1 16 df 15 -D E -%EndDVIPSBitmapFont -/Fg 104[ 91 2[ 45 45 24[ 45 51 47 76 51 55 30 39 36 51 -55 50 53 80 26 51 21 26 53 51 30 44 56 40 50 45 3[ 30 -1[ 30 2[ 61 91 66 71 56 48 61 1[ 55 71 76 86 56 66 30 -31 76 1[ 51 56 70 64 56 71 6[ 23 45 45 45 45 45 45 45 -45 45 45 55 23 30 23 55 1[ 30 30 25 4[ 34 30[ 55 55 2[{ -TeXBase1Encoding ReEncodeFont} 75 90.9091 /Palatino-Roman -rf /Fh 134[ 66 60 100 1[ 73 40 53 47 1[ 73 66 73 106 -2[ 40 40 73 66 47 60 73 53 73 60 11[ 93 80 73 86 1[ 73 -100 100 120 3[ 47 18[ 60 60 60 60 60 60 1[ 35 1[ 40 45[{ -TeXBase1Encoding ReEncodeFont} 38 119.552 /Palatino-Bold -rf /Fi 137[ 50 2[ 39 9[ 28 3[ 39 50 17[ 66 82[{ -TeXBase1Encoding ReEncodeFont} 6 99.6264 /Palatino-Italic -rf /Fj 137[ 56 1[ 32 42 39 2[ 54 58 88 3[ 29 58 55 1[ 48 -61 44 55 50 12[ 61 1[ 67 3[ 83 1[ 61 8[ 71 1[ 78 14[ 50 -50 50 9[ 78 38[{ TeXBase1Encoding ReEncodeFont} 25 99.6264 -/Palatino-Roman rf /Fk 139[ 47 61 57 2[ 78 83 4[ 42 83 -2[ 69 88 64 79 72 12[ 88 4[ 113 119 136 3[ 48 7[ 112 -65[{ TeXBase1Encoding ReEncodeFont} 18 143.462 /Palatino-Roman -rf end -%%EndProlog -%%BeginSetup -%%Feature: *Resolution 600dpi -TeXDict begin -%%PaperSize: A4 - -%%EndSetup -%%Page: 1 1 -1 0 bop Fk 728 918 a(The) 36 b(OMNI) g(Thr) m(ead) f(Abstracti) n(on) p -Fj 1293 1176 a(T) -9 b(ristan) 26 b(Richar) n(dson) 1022 -1293 y(A) -7 b(T&T) 24 b(Laboratories) i(Cambridge) p -Fi 1192 1504 a(Revised) p Fj 24 w(November) f(2001) p -Fh 63 1961 a(1) 119 b(Introduction) p Fg 63 2183 a(The) 20 -b(OMNI) h(thr) n(ead) g(abstraction) g(is) h(des) n(igned) f(to) f(pr) n -(ovide) h(a) h(common) f(set) f(of) h(thr) n(ead) g(oper) n(-) 63 -2296 y(ations) h(for) g(use) g(in) h(pr) n(ograms) f(written) f(in) i -(C++.) 29 b(Pr) n(ograms) 22 b(written) g(using) f(the) h(abstraction) -63 2409 y(should) 30 b(be) g(much) i(easier) e(to) g(port) g(betwee) n -(n) h(dif) n(fer) n(ent) g(ar) n(chi) r(tectur) l(es) g(with) g(dif) n -(fer) n(ent) f(un-) 63 2522 y(derlying) 21 b(thr) n(eads) h -(primitives.) 204 2640 y(The) 17 b(pr) n(ogramming) h(interface) g(is) f -(designed) f(to) h(be) h(similar) h(to) e(the) g(C) i(language) e -(interface) 63 2753 y(to) k(POSIX) h(thr) n(eads) f(\(IEEE) g(draft) h -(standar) n(d) f(100) r(3.1c) i(\227) f(pr) n(eviously) g(1003) r(.4a,) -g(often) g(known) 63 2866 y(as) g(\223pthr) n(eads\224) h([POSIX94]\).) -204 2985 y(Much) 18 b(of) f(the) g(abstraction) i(consists) d(of) i -(simple) g(C++) g(object) g(wrappers) e(ar) n(ound) h(pthr) n(ead) 63 -3098 y(calls.) 28 b(Howe) n(ver) 20 b(for) f(some) f(featur) n(es) g -(such) h(as) h(thr) n(ead-spe) n(ci\002c) h(data,) f(a) f(better) f -(interface) i(can) 63 3211 y(be) i(of) n(fer) n(ed) g(because) h(of) f -(the) g(use) g(of) g(C++.) 204 3329 y(Some) 28 b(of) h(the) f(mor) n(e) -h(complex) f(featur) n(es) g(of) h(pthr) n(eads) f(ar) n(e) h(not) f -(suppo) n(rted) g(because) h(of) 63 3442 y(the) e(dif) n(\002culty) i -(of) f(ensuring) g(the) f(same) h(featur) n(es) g(can) h(be) f(of) n -(fer) n(ed) g(on) g(top) g(of) g(other) f(thr) n(ead) 63 -3555 y(sys) n(tems.) f(Such) 17 b(featur) n(es) g(include) h(thr) n -(ead) f(cancell) r(ation) g(and) h(complex) g(schedu) n(ling) h(contr) n -(ol) 63 3668 y(\(thoug) n(h) k(simple) g(thr) n(ead) f(priorities) g -(ar) n(e) h(supp) n(orted\).) 204 3787 y(The) i(abstraction) h(layer) h -(is) f(curr) n(ently) f(implemented) g(for) h(the) f(following) i(ar) n -(chitectur) n(es) 63 3900 y(/) 22 b(thr) n(ead) h(sys) n(tems:) p -Ff 199 4141 a(\017) p Fg 46 w(Solaris) g(2.x) g(using) f(pthr) n(eads) f -(draft) h(10) p Ff 199 4351 a(\017) p Fg 46 w(Solaris) h(2.x) g(using) f -(solaris) g(thr) n(eads) g(\(but) h(pthr) n(eads) e(version) h(is) h -(now) f(standar) n(d\)) p Ff 199 4561 a(\017) p Fg 46 -w(Alpha) h(OSF1) g(using) f(pthr) n(eads) f(draft) i(4) p -Ff 199 4772 a(\017) p Fg 46 w(W) -5 b(indows) 21 b(NT) h(using) g(NT) g -(thr) n(eads) p Ff 199 4982 a(\017) p Fg 46 w(Linux) g(2.x) h(using) f -(Linuxthr) n(ead) g(0.5) h(\(which) h(is) e(based) g(on) h(pthr) n -(eads) e(draft) i(10\)) p Ff 199 5193 a(\017) p Fg 46 -w(Linux) f(2.x) h(using) f(MIT) g(pthr) n(eads) f(\(which) j(is) f -(based) f(on) g(draft) h(8\)) p Ff 199 5403 a(\017) p -Fg 46 w(A) -7 b(TMos) 22 b(using) g(pthr) n(eads) f(draft) h(6) i -(\(but) e(not) g(V) -5 b(irata) 23 b(A) -7 b(TMos\)) 1684 -5652 y(1) p 90 rotate dyy eop -%%Page: 2 2 -2 1 bop Fg 221 249 a(2) p Fe 1797 w(2) 91 b(SYNCHRONI) n(SA) -7 -b(TION) 22 b(OBJECTS) p Fg 362 548 a(See) h(the) p Fd -22 w(omni) n(thre) n(ad.h) p Fg 22 w(header) f(\002le) i(for) f(full) i -(det) n(ail) r(s) e(of) g(the) g(API.) f(The) h(des) n(criptions) 221 -661 y(below) 35 b(assume) g(you) g(have) h(some) e(pr) n(evious) h -(knowled) n(ge) g(of) h(thr) n(eads) n(,) j(mutexes) n(,) g(condi-) 221 -774 y(tion) f(varia) r(bles) g(and) g(semaphor) n(es) n(.) 75 -b(Also) 38 b(r) n(efer) f(to) h(other) f(document) n(ation) i(\([Birr) n -(ell89) r(],) 221 887 y([POSIX94) q(]\)) 22 b(for) g(further) f -(explanation) i(of) f(thes) n(e) g(ideas) g(\(particularly) h -(condition) f(variab) r(les,) 221 1000 y(the) g(use) g(of) g(which) h -(may) g(not) f(be) h(particularly) h(intuitive) f(when) f(\002rst) f -(encounter) n(ed) n(\).) p Fh 221 1299 a(2) 119 b(Synchronisation) 31 -b(objects) p Fg 221 1510 a(Synchr) n(onisation) 26 b(objects) h(ar) n -(e) g(used) e(to) h(synchr) n(onise) g(thr) n(eads) g(within) h(the) f -(same) h(pr) n(ocess) n(.) 221 1623 y(Ther) n(e) j(is) i(no) f(inter) n -(-pr) n(ocess) f(synchr) n(onisation) g(pr) n(ovided.) 53 -b(The) 30 b(synchr) n(onisation) h(objects) 221 1735 -y(pr) n(ovided) 22 b(ar) n(e) h(mutexes) n(,) g(condition) f(variab) r -(les) g(and) h(counting) f(semaphor) n(e) n(s.) p Fc -221 1991 a(2.1) 99 b(Mutex) p Fg 221 2168 a(An) 26 b(object) g(of) h -(typ) n(e) p Fd 26 w(omni) n(_mute) n(x) p Fg 26 w(is) g(use) n(d) f -(for) h(mutual) f(exclusion.) 39 b(It) 26 b(pr) n(ovides) f(two) g(op-) -221 2281 y(erations,) p Fd 37 w(lock\() n(\)) p Fg 35 -w(and) p Fd 35 w(unloc) n(k\(\)) p Fg(.) 64 b(The) 35 -b(alternative) h(names) p Fd 35 w(acq) n(uire\() n(\)) p -Fg 35 w(and) p Fd 35 w(re-) 221 2393 y(leas) n(e\(\)) p -Fg 19 w(can) 21 b(be) f(used) f(if) i(pr) n(eferr) n(ed) n(.) 27 -b(Behaviour) 20 b(is) g(unde\002ne) n(d) g(when) f(a) i(thr) n(ead) f -(attempt) n(s) 221 2506 y(to) 30 b(lock) h(the) e(same) i(mutex) f -(again) h(or) f(when) g(a) h(mutex) f(is) h(locked) e(by) i(one) e(thr) -n(ead) h(and) h(un-) 221 2619 y(locked) 22 b(by) h(a) g(dif) n(fer) n -(ent) f(thr) n(ead.) p Fc 221 2874 a(2.2) 99 b(Condition) 26 -b(V) -11 b(ariable) p Fg 221 3051 a(A) 28 b(condition) f(varia) r(ble) h -(is) g(r) n(epr) n(ese) n(nted) f(by) h(an) p Fd 28 w(omn) n(i_con) n -(diti) n(on) p Fg 27 w(and) g(is) g(used) e(for) i(sig-) 221 -3164 y(nalli) r(ng) 20 b(betwee) n(n) g(thr) n(eads.) 26 -b(A) 21 b(call) h(to) p Fd 19 w(wait\() n(\)) p Fg 20 -w(causes) e(a) h(thr) n(ead) e(to) h(wait) h(on) f(the) f(condition) 221 -3277 y(varia) r(ble.) 45 b(A) 28 b(call) i(to) p Fd 27 -w(sign) n(al\(\)) p Fg 27 w(wakes) d(up) h(at) g(least) g(one) f(thr) n -(ead) h(if) h(any) f(ar) n(e) g(waiting.) 45 b(A) 221 -3390 y(call) 25 b(to) p Fd 22 w(bro) n(adca) n(st\(\)) p -Fg 21 w(wakes) d(up) g(all) i(thr) n(eads) e(waiting) h(on) f(the) g -(condition) g(varia) r(ble.) 362 3503 y(When) 30 b(constr) o(ucte) n -(d,) i(a) e(pointer) f(to) h(an) p Fd 30 w(omni) n(_mute) n(x) p -Fg 30 w(must) f(be) h(given.) 50 b(A) 30 b(condition) 221 -3616 y(varia) r(ble) p Fd 33 w(wait\() n(\)) p Fg 33 -w(has) j(an) h(implic) r(it) f(mutex) p Fd 33 w(unlo) n(ck\(\)) p -Fg 32 w(and) p Fd 33 w(lock) n(\(\)) p Fg 33 w(ar) n(ound) g(it.) 60 -b(The) 221 3729 y(link) 30 b(between) f(condition) g(varia) r(ble) h -(and) g(mutex) f(lasts) g(for) h(the) f(lifetime) i(of) e(the) g -(condition) 221 3842 y(varia) r(ble) c(\(unlike) h(pthr) n(eads) e -(wher) n(e) g(the) h(link) h(is) f(only) g(for) g(the) g(duration) f -(of) i(the) e(wait\).) 37 b(The) 221 3955 y(same) 23 -b(mutex) f(may) h(be) f(used) f(with) i(several) f(condition) h(variab) -r(les.) 362 4068 y(A) c(wait) g(with) g(a) g(timeout) f(can) i(be) e -(achieved) h(by) g(call) r(ing) p Fd 19 w(tim) n(ed_w) n(ait\(\)) p -Fg -2 w(.) 27 b(This) 18 b(is) h(given) 221 4181 y(an) 27 -b(absolute) e(time) h(to) f(wait) h(until.) 38 b(The) 26 -b(r) n(outine) p Fd 25 w(omn) n(i_thr) n(ead:) n(:get_) n(time) n(\(\)) -p Fg 25 w(can) h(be) 221 4293 y(used) 21 b(to) h(turn) g(a) h(r) n -(elativ) r(e) f(time) g(into) h(an) g(absolute) f(time.) p -Fd 28 w(tim) n(ed_wa) n(it\(\)) p Fg 21 w(r) n(eturns) p -Fd 21 w(true) p Fg 21 w(if) 221 4406 y(the) 27 b(condition) h(was) g -(signalled,) p Fd 29 w(false) p Fg 26 w(if) h(the) f(time) g(expir) n -(ed) f(befor) n(e) g(the) h(condition) f(vari) r(-) 221 -4519 y(able) d(was) e(signalled.) p Fc 221 4774 a(2.3) 99 -b(Counting) 26 b(semaphores) p Fg 221 4951 a(An) p Fd -21 w(omn) n(i_sem) n(apho) n(re) p Fg 20 w(is) 21 b(a) h(counting) e -(semaphor) n(e) n(.) 28 b(When) 20 b(cr) n(eated) g(it) h(is) g(given) g -(an) g(initial) 221 5064 y(unsigned) j(intege) n(r) i(value.) 36 -b(When) p Fd 25 w(wai) n(t\(\)) p Fg 24 w(is) 26 b(called,) g(the) f -(value) h(is) f(decr) n(emente) n(d) g(if) h(non-) 221 -5177 y(zer) n(o.) 43 b(If) 27 b(the) g(value) h(is) f(zer) n(o) h(then) -f(the) f(thr) n(ead) h(blocks) h(instead.) 41 b(When) p -Fd 27 w(post) n(\(\)) p Fg 27 w(is) 27 b(cal) r(led,) 221 -5290 y(if) h(any) g(thr) n(eads) e(ar) n(e) i(blocked) f(in) p -Fd 27 w(wait\() n(\)) p Fg(,) h(exactly) f(one) g(thr) n(ead) g(is) g -(woken.) 41 b(If) 27 b(no) g(thr) n(eads) 221 5403 y(wer) n(e) 22 -b(blocked) g(then) g(the) g(value) h(of) g(the) e(semaphor) n(e) h(is) h -(incr) n(emented.) p 90 rotate dyy eop -%%Page: 3 3 -3 2 bop Fg 3306 249 a(3) 204 548 y(If) 27 b(a) h(thr) n(ead) e(cal) r -(ls) p Fd 27 w(try) n(_wait) n(\(\)) p Fg(,) h(then) g(the) f(thr) n -(ead) g(won't) h(block) h(if) f(the) g(semaphor) n(e's) 63 -661 y(value) c(is) g(0,) g(r) n(eturning) p Fd 21 w(false) p -Fg 21 w(instead.) 204 777 y(Ther) n(e) f(is) g(no) h(way) f(of) h -(query) n(ing) g(the) f(value) h(of) g(the) f(semaphor) n(e) n(.) p -Fh 63 1095 a(3) 119 b(Thread) 29 b(object) p Fg 63 1313 -a(A) 23 b(thr) n(ead) g(is) h(r) n(epr) n(ese) n(nted) e(by) i(an) p -Fd 24 w(omni) n(_thr) n(ead) p Fg 23 w(object.) 30 b(Ther) n(e) 23 -b(ar) n(e) h(br) n(oadly) g(two) e(dif) n(fer) n(-) 63 -1426 y(ent) f(ways) i(in) g(which) g(it) g(can) g(be) g(used) n(.) 204 -1542 y(The) 28 b(\002rst) g(way) h(is) h(simply) f(to) f(cr) n(eate) h -(an) p Fd 30 w(omn) n(i_thr) n(ead) p Fg 28 w(object,) h(giving) g(a) f -(particula) r(r) 63 1655 y(function) c(which) h(the) e(thr) n(ead) h -(should) f(execute) n(.) 36 b(This) 25 b(is) g(like) g(the) g(POSIX) f -(\(or) i(any) f(other) n(\)) h(C) 63 1768 y(language) c(interface.) 204 -1884 y(The) k(second) f(method) h(of) h(use) e(is) i(to) f(cr) n(eate) h -(a) g(new) g(class) g(which) g(inherits) f(fr) n(om) p -Fd 28 w(omn) n(i_) 63 1997 y(thr) n(ead) p Fg(.) 50 b(In) 31 -b(this) f(case) g(the) g(thr) n(ead) g(will) i(execute) d(the) p -Fd 29 w(run\(\)) p Fg 29 w(member) h(function) h(of) f(the) 63 -2109 y(new) 22 b(class.) 29 b(One) 23 b(advantage) g(of) g(this) g -(scheme) f(is) h(that) g(thr) n(ead-speci\002c) g(data) g(can) h(be) f -(imple-) 63 2222 y(mented) e(simply) h(by) h(having) g(data) g(members) -f(of) h(the) f(new) g(class.) 204 2339 y(When) f(constr) o(ucted) g(a) i -(thr) n(ead) f(is) g(in) h(the) e("new") h(state) f(and) h(has) g(not) g -(actuall) r(y) g(starte) n(d.) 28 b(A) 63 2451 y(call) j(to) p -Fd 29 w(sta) n(rt\(\)) p Fg 28 w(causes) e(the) g(thr) n(ead) g(to) g -(begin) g(executing.) 47 b(A) 29 b(static) h(member) f(function) p -Fd 63 2564 a(cre) n(ate\() n(\)) p Fg 32 w(is) j(pr) n(ovided) f(to) g -(constr) o(uct) g(and) g(start) g(a) i(thr) n(ead) e(in) h(a) g(single) -g(call.) 57 b(A) 31 b(thr) n(ead) 63 2677 y(exits) 21 -b(by) i(call) r(ing) p Fd 22 w(exit\() n(\)) p Fg 22 -w(or) g(by) f(r) n(eturning) g(fr) n(om) h(the) f(thr) n(ead) g -(function.) 204 2793 y(Thr) n(eads) 27 b(can) j(be) e(either) g -(detached) f(or) h(undetached) n(.) 46 b(Detached) 28 -b(thr) n(eads) g(ar) n(e) h(thr) n(eads) 63 2906 y(for) h(which) i(all) -g(state) e(will) i(be) f(lost) f(upon) g(exit.) 52 b(Other) 30 -b(thr) n(eads) g(cannot) h(dete) n(rmine) g(when) 63 -3019 y(a) e(detached) f(thr) n(ead) h(will) h(disappear) -7 -b(,) 31 b(and) e(ther) n(efor) n(e) f(should) g(not) h(attempt) f(to) g -(access) h(the) 63 3132 y(thr) n(ead) 23 b(object) g(unless) f(some) h -(explicit) h(synchr) n(onisation) f(with) g(the) g(detached) f(thr) n -(ead) h(guar) n(-) 63 3245 y(antees) e(that) h(it) h(still) g(exists.) -204 3361 y(Undet) n(ached) 33 b(thr) n(eads) f(ar) n(e) i(thr) n(eads) e -(for) h(which) g(storage) f(is) h(not) f(r) n(eclai) r(med) g(until) i -(an-) 63 3474 y(othe) n(r) g(thr) n(ead) g(waits) g(for) g(its) g -(termination) g(by) g(call) r(ing) p Fd 34 w(joi) n(n\(\)) p -Fg(.) 61 b(An) 34 b(exit) g(value) h(can) g(be) 63 3587 -y(passe) n(d) 23 b(fr) n(om) g(an) g(undet) n(ached) g(thr) n(ead) f -(to) g(the) g(thr) n(ead) g(which) h(joins) g(it.) 204 -3703 y(Detached) 31 b(/) h(undetached) e(thr) n(eads) h(ar) n(e) i -(distinguish) n(ed) f(on) f(cr) n(eation) h(by) g(the) f(type) g(of) 63 -3816 y(function) 24 b(they) e(execute.) 30 b(Undetached) 22 -b(thr) n(eads) h(execute) g(a) h(function) g(which) g(has) g(a) p -Fd 25 w(voi) n(d*) p Fg 63 3929 a(r) n(eturn) c(typ) n(e,) h(wher) n -(eas) f(detached) f(thr) n(eads) h(execute) f(a) j(function) f(which) g -(has) g(a) p Fd 21 w(void) p Fg 19 w(r) n(eturn) 63 4042 -y(typ) n(e.) 52 b(Unfortunate) n(ly) 31 b(C++) g(member) g(functions) f -(ar) n(e) h(not) f(allowed) g(to) g(be) h(distingu) n(ished) 63 -4155 y(simply) 26 b(by) h(their) f(r) n(eturn) g(type) n(.) 40 -b(Thus) 26 b(in) h(the) f(case) h(of) g(a) g(derived) f(class) h(of) p -Fd 26 w(omni_) n(thre) n(ad) p Fg 63 4268 a(which) 20 -b(needs) e(an) j(undet) n(ached) f(thr) n(ead,) g(the) f(member) h -(function) g(execute) n(d) g(by) g(the) f(thr) n(ead) g(is) 63 -4380 y(called) p Fd 19 w(run_u) n(ndet) n(ache) n(d\(\)) p -Fg 18 w(rather) f(than) p Fd 19 w(run\() n(\)) p Fg(,) h(and) g(it) g -(is) g(started) e(by) i(calli) r(ng) p Fd 18 w(star) n(t_) 63 -4493 y(und) n(etac) n(hed\(\)) p Fg 21 w(instead) j(of) p -Fd 22 w(start) n(\(\)) p Fg(.) 204 4610 y(The) i(abstraction) i(curr) n -(ently) e(suppo) n(rts) h(thr) n(ee) f(priorities) g(of) h(thr) n(ead,) -g(but) g(no) g(guarantee) 63 4722 y(is) 33 b(made) g(of) h(how) f(this) -g(will) h(af) n(f) r(ect) f(underlying) f(thr) n(ead) h(scheduling.) 59 -b(The) 33 b(thr) n(ee) f(priori-) 63 4835 y(ties) 18 -b(ar) n(e) p Fd 20 w(PRIO) n(RITY) n(_LOW) p Fg(,) p -Fd 18 w(PRIO) n(RITY) n(_NOR) n(MAL) p Fg 19 w(and) p -Fd 19 w(PRIO) n(RITY) n(_HIG) n(H) p Fg(.) h(By) g(default) g(all) 63 -4948 y(thr) n(eads) i(r) o(un) i(at) p Fd 23 w(PRIO) n(RITY) n(_NORM) n -(AL) p Fg(.) f(A) g(dif) n(fer) n(ent) h(priority) f(can) i(be) e -(speci\002ed) g(on) g(thr) n(ead) 63 5061 y(cr) n(eation,) h(or) f -(while) h(the) f(thr) n(ead) g(is) h(r) o(unning) g(using) p -Fd 22 w(set_) n(prio) n(rity\() n(\).) p Fg 28 w(A) g(thr) n(ead's) f -(cur) n(-) 63 5174 y(r) n(ent) g(priority) g(is) g(r) n(eturned) f(by) p -Fd 23 w(pri) n(ority) n(\(\)) p Fg(.) 204 5290 y(Other) d(functions) g -(pr) n(ovided) g(ar) n(e) p Fd 19 w(sel) n(f\(\)) p Fg -18 w(which) h(r) n(eturns) e(the) h(calli) r(ng) g(thr) n(ead's) p -Fd 18 w(omn) n(i_) 63 5403 y(thr) n(ead) p Fg 36 w(object,) p -Fd 40 w(yie) n(ld\(\)) p Fg 35 w(which) 38 b(r) n(eques) n(ts) e(that) h -(other) e(thr) n(eads) h(be) h(allowed) g(to) f(r) o(un,) p -90 rotate dyy eop -%%Page: 4 4 -4 3 bop Fg 221 249 a(4) p Fe 1367 w(6) 91 b(THRE) n(ADED) 23 -b(I/O) g(SHUTDOWN) f(FOR) g(UNIX) p Fd 221 548 a(id\(\)) p -Fg 27 w(which) 29 b(r) n(eturns) e(an) i(intege) n(r) g(id) f(for) h -(the) e(thr) n(ead) h(for) g(use) g(in) h(debug) n(ging,) p -Fd 29 w(state) n(\(\)) p Fg(,) p Fd 221 661 a(slee) n(p\(\)) p -Fg 22 w(and) p Fd 22 w(get_t) n(ime\() n(\)) p Fg(.) p -Fh 221 953 a(4) 119 b(Per) n(-threa) n(d) 30 b(data) p -Fg 221 1164 a(omnithr) n(ead) 22 b(suppo) n(rts) g(per) n(-thr) n(ead) f -(data,) h(via) i(member) e(functions) f(of) i(the) p -Fd 21 w(omni) n(_thr) n(ead) p Fg 221 1277 a(object.) 362 -1390 y(First,) d(you) g(must) h(allocate) h(a) f(key) f(for) g(with) h -(the) p Fd 20 w(omni) n(_thre) n(ad::) n(allo) n(cate_) n(key\() n(\)) p -Fg 221 1502 a(function.) 28 b(Then,) 21 b(any) h(object) g(whose) f -(class) h(is) g(derived) f(fr) n(om) p Fd 23 w(omni) n(_thr) n(ead::) n -(valu) n(e_t) p Fg 221 1615 a(can) 27 b(be) f(stor) n(e) n(d) g(using) f -(the) p Fd 26 w(set) n(_val) n(ue\(\)) p Fg 25 w(function.) 38 -b(V) -8 b(alues) 25 b(ar) n(e) h(r) n(etrieved) f(or) h(r) n(emoved) 221 -1728 y(with) p Fd 23 w(get) n(_valu) n(e\(\)) p Fg 21 -w(and) p Fd 23 w(remo) n(ve_v) n(alue\() n(\)) p Fg 22 -w(r) n(espectively) -10 b(.) 362 1841 y(When) 23 b(the) g(thr) n(ead) g -(exits,) g(all) i(per) n(-thr) n(ead) e(data) h(is) g(delet) n(ed) f -(\(hence) h(the) e(base) i(class) g(with) 221 1954 y(virtual) g(dest) n -(r) o(uctor\).) 362 2067 y(Note) 17 b(that) i(the) f(per) n(-thr) n -(ead) f(data) i(functions) f(ar) n(e) p Fb 19 w(not) p -Fg 18 w(thr) n(ead) g(safe,) i(so) d(although) i(you) e(can) 221 -2180 y(access) 29 b(one) e(thr) n(ead's) h(storage) f(fr) n(om) i -(another) f(thr) n(ead,) h(ther) n(e) e(is) i(no) f(concurr) n(ency) g -(contr) n(ol.) 221 2293 y(Unless) j(you) g(r) n(eall) r(y) h(know) f -(what) h(you) f(ar) n(e) i(doing,) g(it) g(is) f(best) f(to) h(only) g -(access) g(per) n(-thr) n(ead) 221 2406 y(data) 23 b(fr) n(om) g(the) f -(thr) n(ead) g(it) h(is) g(attached) f(to.) p Fh 221 -2698 a(5) 119 b(Using) 31 b(OMNI) d(threads) h(in) h(your) g(program) p -Fg 221 2909 a(Obvi) r(ously) 16 b(you) h(need) g(to) g(include) h(the) p -Fd 16 w(omnit) n(hrea) n(d.h) p Fg 17 w(header) e(\002le) i(in) g(your) -f(sour) n(ce) g(code,) 221 3021 y(and) 25 b(link) g(in) h(the) e -(omnithr) n(ead) g(libra) r(ry) g(with) h(your) f(execut) n(abl) r(e.) -34 b(Because) 23 b(ther) n(e) h(is) h(a) g(single) p -Fd 221 3134 a(omni) n(threa) n(d.h) p Fg 30 w(for) 32 -b(all) h(platforms,) h(certain) e(pr) n(epr) n(oces) n(sor) f -(de\002nes) f(must) h(be) g(given) h(as) 221 3247 y(compiler) 25 -b(options) n(.) 33 b(The) 23 b(easiest) g(way) h(to) g(do) f(this) h -(is) g(to) g(stud) n(y) g(the) g(make\002les) f(given) h(in) h(the) 221 -3360 y(examples) i(pr) n(ovided) g(with) g(this) g(distribution.) 42 -b(If) 27 b(you) g(ar) n(e) g(to) g(include) h(OMNI) f(thr) n(eads) g -(in) 221 3473 y(your) 18 b(own) g(development) g(envir) n(onment,) h -(thes) n(e) g(ar) n(e) g(the) f(necessary) g(pr) n(epr) n(oce) n(ssor) g -(de\002nes) n(:) p 362 3567 3287 4 v 360 3680 4 113 v -412 3646 a(Platform) p 1312 3680 V 599 w(Pr) n(epr) n(ocess) n(or) 23 -b(De\002nes) p 3648 3680 V 362 3683 3287 4 v 362 3700 -V 360 3813 4 113 v 412 3779 a(Sun) f(Solaris) h(2.x) p -1312 3813 V Fd 365 w(-D__) n(suno) n(s__) 54 b(-D_) n(_spa) n(rc__) f -(-D__) n(OSVER) n(SION) n(__=5) p 3648 3813 V 360 3926 -V 1312 3926 V 1363 3892 a(-DSV) n(R4) h(-DUs) n(ePth) n(read) f(-D_R) n -(EENT) n(RANT) p 3648 3926 V 362 3929 3287 4 v 360 4042 -4 113 v Fg 412 4008 a(x86) 24 b(Linux) e(2.0) p 1312 -4042 V Fd 418 w(-D__) n(linu) n(x__) 54 b(-D_) n(_i86) n(__) g(-D__) n -(OSVE) n(RSION) n(__=2) p 3648 4042 V 360 4155 V Fg 412 -4121 a(with) 23 b(linuxthr) n(eads) f(0.5) p 1312 4155 -V Fd 100 w(-D_R) n(EENT) n(RANT) p 3648 4155 V 362 4158 -3287 4 v 360 4271 4 113 v Fg 412 4237 a(Digital) i(Unix) f(3.2) p -1312 4271 V Fd 320 w(-D__) n(osf1) n(__) 54 b(-D__) n(alph) n(a__) g -(-D_) n(_OSV) n(ERSIO) n(N__=) n(3) p 3648 4271 V 360 -4384 V 1312 4384 V 1363 4350 a(-D_R) n(EENT) n(RANT) p -3648 4384 V 362 4387 3287 4 v 360 4500 4 113 v Fg 412 -4466 a(W) -5 b(indows) 22 b(NT) p 1312 4500 V Fd 411 -w(-D__) n(NT__) 53 b(-MD) p 3648 4500 V 362 4503 3287 -4 v Fh 221 4740 a(6) 119 b(Threaded) 29 b(I/O) g(shutdown) h(for) g -(Unix) p Fg 221 4951 a(or) -7 b(,) 20 b(how) e(one) g(thr) n(ead) h -(shou) n(ld) h(tell) f(another) f(thr) n(ead) g(to) h(shut) f(down) g -(when) g(it) h(might) g(be) g(doing) 221 5064 y(a) k(blocking) g(cal) r -(l) g(on) f(a) h(socket) n(.) p Fb 362 5177 a(If) h(you) e(are) i -(using) e(omniOR) n(B,) h(you) e(don') n(t) i(need) g(to) g(worry) f -(about) g(all) i(this,) f(since) h(om-) 221 5290 y(niORB) i(does) h(it) -h(for) f(you) n(.) p Fg 41 w(This) g(section) f(is) h(only) g(r) n -(elevant) g(if) h(you) e(ar) n(e) h(using) f(omnithr) n(ead) 221 -5403 y(in) d(your) f(own) g(socket) n(-based) h(pr) n(ogramming.) k(It) -22 b(is) h(also) g(serious) n(ly) g(out) f(of) h(date.) p -90 rotate dyy eop -%%Page: 5 5 -5 4 bop Fe 63 249 a(6.1) 91 b(r) n(ead\(\)) p Fg 2800 -w(5) 204 548 y(Unfortunate) n(ly) 35 b(ther) n(e) e(doe) n(sn't) h -(seem) f(to) h(be) g(a) h(standar) n(d) e(way) i(of) f(doing) f(this) h -(which) 63 661 y(works) 19 b(acr) n(oss) i(all) i(Unix) e(syst) n(ems.) -27 b(I) 21 b(have) g(investigated) f(the) h(behaviour) g(of) g(Solaris) -h(2.5) g(and) 63 774 y(Digital) k(Unix) g(3.2.) 36 b(On) 26 -b(Digital) h(Unix) e(everyth) n(ing) h(is) f(\002ne,) g(as) h(the) e -(obvious) h(method) f(using) 63 887 y(shutd) n(own\(\)) 32 -b(seems) f(to) h(work) f(OK.) h(Unfortunately) f(on) h(Solaris) h(shut) -n(down) f(can) h(only) f(be) 63 1000 y(used) 25 b(on) h(a) h(connected) -e(socke) n(t,) i(so) f(we) g(need) f(devious) h(means) g(to) g(get) f -(ar) n(ound) h(this) g(lim) r(ita-) 63 1112 y(tion.) h(The) 22 -b(details) g(ar) n(e) h(summarised) g(below:) p Fc 63 -1429 a(6.1) 99 b(read\(\)) p Fg 63 1627 a(Thr) n(ead) 28 -b(A) h(is) g(in) h(a) g(loop,) g(doing) p Fd 28 w(rea) n(d\(soc) n(k\)) -p Fg(,) g(pr) n(ocess) n(ing) f(the) g(data,) h(then) f(going) f(back) -63 1739 y(into) 22 b(the) g(r) n(ead.) 204 1862 y(Thr) n(ead) 30 -b(B) h(comes) f(along) h(and) g(wants) f(to) g(shut) g(it) h(down) f -(\227) h(it) g(can't) g(cancel) h(thr) n(ead) f(A) 63 -1975 y(since) 21 b(\(i\)) h(working) e(out) g(how) g(to) h(clean) h(up) -e(accor) n(ding) i(to) e(wher) n(e) g(A) h(is) g(in) h(its) f(loop) f -(is) h(a) h(night-) 63 2088 y(mar) n(e,) h(and) f(\(ii\)) i(this) f -(isn't) f(ava) r(ilabl) r(e) g(in) h(omnithr) n(ead) f(anyway) -10 -b(.) 204 2211 y(On) 23 b(Solaris) g(2.5) g(and) g(Digital) h(Unix) f -(3.2) g(the) f(following) h(strate) n(gy) f(works:) 204 -2334 y(Thr) n(ead) g(B) g(does) p Fd 21 w(shut) n(down\() n(sock) n -(,2\)) p Fg(.) 204 2457 y(At) g(this) g(point) h(thr) n(ead) f(A) g(is) -h(either) f(blocked) g(inside) p Fd 23 w(rea) n(d\(so) n(ck\)) p -Fg(,) g(or) g(is) h(elsewhe) n(r) n(e) g(in) 63 2570 -y(the) 18 b(loop.) 26 b(If) 18 b(the) g(former) h(then) f(r) n(ead) h -(will) h(r) n(eturn) e(0,) i(indicating) f(that) g(the) f(socke) n(t) h -(is) g(closed.) 26 b(If) 63 2683 y(the) 21 b(latter) h(then) f -(eventually) h(thr) n(ead) g(A) g(will) i(call) p Fd -24 w(rea) n(d\(so) n(ck\)) p Fg 21 w(and) f(then) e(this) h(will) h(r) n -(eturn) 63 2796 y(0.) 28 b(Thr) n(ead) 22 b(A) h(should) p -Fd 21 w(clos) n(e\(soc) n(k\)) p Fg(,) f(do) g(any) g(other) g(tidying) -f(up,) h(and) h(exit.) 204 2919 y(If) 34 b(ther) n(e) g(is) h(another) f -(point) g(in) h(the) e(loop) i(that) f(thr) n(ead) g(A) h(can) g(block) -g(then) f(obviously) 63 3032 y(thr) n(ead) 19 b(B) h(needs) f(to) h(be) -g(awar) n(e) h(of) f(this) g(and) g(be) h(able) g(to) e(wake) h(it) h -(up) f(in) g(the) g(appr) n(opriate) g(way) 63 3145 y(fr) n(om) j(that) -f(point.) p Fc 63 3462 a(6.2) 99 b(accept\(\)) p Fg 63 -3659 a(Again) 25 b(thr) n(ead) g(A) h(is) f(in) h(a) g(loop,) g(this) f -(time) h(doing) e(an) i(acc) r(ept) e(on) h(listenSock,) g(dealing) h -(with) 63 3772 y(a) d(new) f(connection) g(and) h(going) e(back) j -(into) e(accept.) 28 b(Thr) n(ead) 22 b(B) g(wants) h(to) f(cancel) h -(it.) 204 3895 y(On) g(Digital) h(Unix) f(3.2) g(the) f(strateg) n(y) g -(is) h(identical) h(to) e(that) g(for) h(r) n(ead:) 204 -4018 y(Thr) n(ead) 39 b(B) g(does) p Fd 38 w(shut) n(down) n(\(list) n -(enSo) n(ck,2) n(\)) p Fg(.) 79 b(Wher) n(ever) 38 b(thr) n(ead) h(A) h -(is) f(in) h(the) 63 4131 y(loop,) i(eventually) c(it) h(will) h(r) n -(eturn) p Fd 38 w(ECONN) n(ABOR) n(TED) p Fg 38 w(fr) n(om) f(the) f -(accept) h(call) r(.) 76 b(It) 39 b(shou) n(ld) p Fd -63 4244 a(clo) n(se\(l) n(isten) n(Sock) n(\)) p Fg(,) 22 -b(tidy) g(up) g(as) h(necessary) e(and) i(exit.) 204 -4367 y(On) 30 b(Solaris) f(2.5) i(thr) n(ead) e(B) g(can't) h(do) p -Fd 29 w(shu) n(tdow) n(n\(lis) n(tenS) n(ock,2) n(\)) p -Fg 29 w(\227) g(this) f(r) n(eturns) p Fd 63 4480 a(ENO) n(TCON) n(N) p -Fg(.) 22 b(Instead) f(the) h(following) h(strateg) n(y) g(can) g(be) g -(used) n(:) 204 4603 y(First) 35 b(thr) n(ead) h(B) g(set) n(s) g(some) -f(sort) g(of) h("shutdo) n(wn) g(\003ag") g(associated) g(with) g -(listenSock.) 63 4716 y(Then) 31 b(it) h(does) p Fd 30 -w(gets) n(ocka) n(ddr\(l) n(iste) n(nSock) n(\)) p Fg -32 w(to) f(\002nd) g(out) g(which) i(port) e(listenSock) f(is) 63 -4828 y(on) 18 b(\(or) h(knows) e(alr) n(eady\),) j(sets) d(up) h(a) h -(socket) e(dummySock,) i(doe) n(s) p Fd 19 w(con) n(nect) n(\(dumm) n -(ySoc) n(k,) 63 4941 y(thi) n(s) 54 b(host,) f(por) n(t\)) p -Fg 22 w(and) 23 b(\002nally) g(does) p Fd 21 w(clos) n(e\(dum) n(mySo) n -(ck\)) p Fg(.) 204 5064 y(Wher) n(ever) 16 b(thr) n(ead) h(A) g(is) g -(in) h(the) e(loop,) h(eventually) g(it) h(will) g(call) p -Fd 19 w(acce) n(pt\(li) n(sten) n(Sock) n(\)) p Fg(.) 63 -5177 y(This) 35 b(will) j(r) n(eturn) d(successfully) g(with) h(a) h -(new) e(socket,) j(say) e(connSock.) 67 b(Thr) n(ead) 36 -b(A) f(then) 63 5290 y(checks) 20 b(to) h(see) f(if) i(the) f("shutd) n -(own) g(\003ag") h(is) f(set.) 26 b(If) c(not,) e(then) h(it's) g(a) h -(normal) g(connection.) 27 b(If) 21 b(it) 63 5403 y(is) h(set,) g(then) -f(thr) n(ead) h(A) h(closes) f(listenSock) f(and) i(connSock,) e -(tidies) h(up) g(and) h(exits.) p 90 rotate dyy eop -%%Page: 6 6 -6 5 bop Fg 221 249 a(6) p Fe 1367 w(6) 91 b(THRE) n(ADED) 23 -b(I/O) g(SHUTDOWN) f(FOR) g(UNIX) p Fc 221 548 a(6.3) 99 -b(write\(\)) p Fg 221 768 a(Thr) n(ead) 19 b(A) f(may) h(be) g(blocked) -f(in) i(write,) f(or) f(about) h(to) f(go) g(in) h(to) g(a) g(poten) n -(tiall) r(y-blocking) g(write.) 221 881 y(Thr) n(ead) j(B) h(wants) f -(to) g(shut) f(it) i(down.) 362 1016 y(On) g(Solaris) g(2.5:) 362 -1150 y(Thr) n(ead) f(B) h(doe) n(s) p Fd 23 w(shu) n(tdown) n(\(soc) n -(k,2\)) p Fg -2 w(.) 362 1285 y(If) c(thr) n(ead) f(A) h(is) g(alr) n -(eady) g(in) p Fd 20 w(wri) n(te\(s) n(ock\)) p Fg 17 -w(then) f(it) h(will) i(r) n(eturn) d(with) p Fd 18 w(ENXIO) p -Fg -2 w(.) h(If) g(thr) n(ead) 221 1398 y(A) k(calls) h(write) e(after) -g(thr) n(ead) g(B) h(calls) h(shut) n(down) e(this) g(will) i(r) n -(eturn) p Fd 22 w(EIO) p Fg(.) 362 1532 y(On) f(Digital) h(Unix) f -(3.2:) 362 1666 y(Thr) n(ead) f(B) h(doe) n(s) p Fd 23 -w(shu) n(tdown) n(\(soc) n(k,2\)) p Fg -2 w(.) 362 1801 -y(If) h(thr) n(ead) f(A) g(is) h(alr) n(eady) g(in) p -Fd 24 w(writ) n(e\(so) n(ck\)) p Fg 23 w(then) e(it) i(will) h(r) n -(eturn) e(the) f(number) i(of) f(bytes) 221 1914 y(written) 31 -b(befor) n(e) h(it) g(became) g(blocked.) 55 b(A) 32 -b(subseq) n(uent) f(cal) r(l) h(to) f(write) h(will) h(then) e(gene) n -(rate) p Fd 221 2027 a(SIGP) n(IPE) p Fg 22 w(\(or) p -Fd 22 w(EPIP) n(E) p Fg 23 w(will) 24 b(be) e(r) n(eturned) f(if) p -Fd 24 w(SIG) n(PIPE) p Fg 21 w(is) i(ignor) n(ed) e(by) i(the) f(thr) n -(ead\).) p Fc 221 2413 a(6.4) 99 b(connect\(\)) p Fg -221 2634 a(Thr) n(ead) 30 b(A) f(may) h(be) g(blocked) f(in) i -(connect,) g(or) e(about) h(to) f(go) g(in) i(to) e(a) h(poten) n -(tiall) r(y-blocking) 221 2747 y(connect.) d(Thr) n(ead) c(B) f(wants) g -(to) g(shut) g(it) g(down.) 362 2881 y(On) h(Digital) h(Unix) f(3.2:) -362 3016 y(Thr) n(ead) f(B) h(doe) n(s) p Fd 23 w(shu) n(tdown) n -(\(soc) n(k,2\)) p Fg -2 w(.) 362 3150 y(If) j(thr) n(ead) f(A) g(is) h -(alr) n(eady) g(in) p Fd 26 w(conn) n(ect\() n(sock) n(\)) p -Fg 26 w(then) e(it) i(will) h(r) n(eturn) e(a) h(successful) f(con-) 221 -3263 y(nection.) 54 b(Subsequ) n(ent) 31 b(r) n(eading) g(or) g -(writing) g(will) i(show) d(that) i(the) e(socket) g(has) h(been) g -(shut) 221 3376 y(down) 22 b(\(i.e.) 28 b(r) n(ead) 23 -b(r) n(eturns) e(0,) i(write) f(generate) n(s) p Fd 23 -w(SIG) n(PIPE) p Fg 21 w(or) g(r) n(eturns) p Fd 22 w(EPI) n(PE) p -Fg(\).) g(If) h(thr) n(ead) f(A) 221 3489 y(call) r(s) g(connect) g -(after) h(thr) n(ead) f(B) g(call) r(s) g(shutdo) n(wn) h(this) f(will) -i(r) n(eturn) p Fd 22 w(EIN) n(VAL) p Fg(.) 362 3623 -y(On) f(Solaris) g(2.5:) 362 3758 y(Ther) n(e) 35 b(is) h(no) f(way) g -(to) g(wake) g(up) g(a) h(thr) n(ead) f(which) h(is) g(blocked) f(in) h -(connect.) 66 b(Inst) n(ead) 221 3871 y(Solaris) 33 b(for) n(ces) g(us) -f(thr) n(ough) g(a) i(ridiculous) f(pr) n(oced) n(ur) n(e) g(whichever) -g(way) g(we) f(try) g(it.) 59 b(One) 221 3984 y(way) 23 -b(is) f(this:) 362 4118 y(First) d(thr) n(ead) h(A) g(cr) n(eates) f(a) -h(pipe) g(in) g(addition) g(to) f(the) g(socket) n(.) 27 -b(Instead) 19 b(of) h(shut) n(ting) g(down) 221 4231 -y(the) i(socket) n(,) h(thr) n(ead) f(B) g(simply) h(writes) e(a) i -(byte) f(to) g(the) g(pipe.) 362 4365 y(Thr) n(ead) 17 -b(A) g(meanwhile) h(set) n(s) f(the) g(socke) n(t) g(to) g -(non-blocking) g(mode) f(using) p Fd 17 w(fcn) n(tl\(s) n(ock,) 221 -4478 y(F_SE) n(TFL,) 53 b(O_NO) n(NBLO) n(CK\)) p Fg(.) 26 -b(Then) h(it) g(cal) r(ls) g(connect) g(on) g(the) f(socket) g(\227) h -(this) g(will) i(r) n(eturn) p Fd 221 4591 a(EINP) n(ROGRE) n(SS) p -Fg(.) k(Then) h(it) h(must) e(cal) r(l) p Fd 35 w(sel) n(ect\() n(\)) p -Fg(,) k(waiting) e(for) f(either) g(sock) g(to) f(become) 221 -4704 y(writable) 39 b(or) f(for) h(the) e(pipe) h(to) g(become) g(r) n -(eadable.) 75 b(If) 39 b(select) e(r) n(eturns) g(that) i(just) e(sock) -h(is) 221 4817 y(writable) 30 b(then) f(the) g(connection) g(has) h -(succeede) n(d.) 49 b(It) 29 b(then) g(need) n(s) h(to) f(set) f(the) h -(socket) f(back) 221 4930 y(to) i(blocking) h(mode) f(using) p -Fd 30 w(fcnt) n(l\(so) n(ck,) 54 b(F_S) n(ETFL) n(,) h(0\)) p -Fg(.) c(If) 31 b(instead) e(select) h(r) n(eturns) 221 -5043 y(that) 23 b(the) e(pipe) h(is) h(r) n(eadable,) g(thr) n(ead) f -(A) h(closes) e(the) h(socket) n(,) h(tidies) f(up) g(and) h(exits.) 362 -5177 y(An) g(alternative) h(method) e(is) i(similar) h(but) e(to) g -(use) f(polling) i(instead) e(of) i(the) e(pipe.) 29 -b(Thr) n(ead) 221 5290 y(B) 24 b(justs) e(sets) g(a) j(\003ag) f(and) g -(thr) n(ead) f(A) h(calls) h(select) e(with) g(a) i(timeout,) e(period) -n(ica) r(lly) h(waking) f(up) 221 5403 y(to) f(see) g(if) h(the) f -(\003ag) h(has) f(been) g(set.) p 90 rotate dyy eop -%%Page: 7 7 -7 6 bop Fe 63 249 a(REF) n(ERENCES) p Fg 2660 w(7) p -Fh 63 548 a(Refere) n(nces) p Fg 63 759 a([POSIX94]) p -Fa 46 w(Portable) 29 b(Operat) r(ing) f(System) g(Interface) h -(\(POSIX\)) e(Thr) n(ea) r(ds) h(Extension) p Fg(,) h(P1003) r(.1c) 245 -872 y(Draft) 23 b(10,) g(IEEE,) e(Septe) n(mber) i(1994) r(.) 63 -1059 y([Birr) n(ell89]) p Fa 47 w(An) 28 b(Intr) n(od) r(uction) g(to) h -(Pr) n(ogr) r(amming) g(with) g(Thr) n(ead) r(s) p Fg(,) h(Rese) n(ar) n -(ch) g(Repo) n(rt) e(35,) j(DEC) 245 1172 y(Syst) n(ems) 22 -b(Resear) n(ch) g(Center) -7 b(,) 22 b(Palo) h(Alto,) f(CA,) h(January) -g(1989) r(.) p 90 rotate dyy eop -%%Trailer -end -userdict /end-hook known{end-hook}if -%%EOF diff --git a/gcell/apps/Makefile.am b/gcell/apps/Makefile.am index 7cf9122a..c3a2092a 100644 --- a/gcell/apps/Makefile.am +++ b/gcell/apps/Makefile.am @@ -22,9 +22,7 @@ include $(top_srcdir)/Makefile.common SUBDIRS = spu . -AM_CPPFLAGS = $(DEFINES) $(OMNITHREAD_INCLUDES) \ - $(GCELL_INCLUDES) $(CPPUNIT_INCLUDES) $(WITH_INCLUDES) - +AM_CPPFLAGS = $(DEFINES) $(GCELL_INCLUDES) $(CPPUNIT_INCLUDES) $(WITH_INCLUDES) GCELL_QA_LA = $(top_builddir)/gcell/lib/libgcell-qa.la diff --git a/gcell/gcell.pc.in b/gcell/gcell.pc.in index d88d0fb6..e602ff7c 100644 --- a/gcell/gcell.pc.in +++ b/gcell/gcell.pc.in @@ -6,7 +6,7 @@ gcell_embedspu_libtool=@bindir@/gcell-embedspu-libtool Name: gcell Description: The GNU Radio SPE scheduler and RPC mechanism -Requires: gnuradio-omnithread +Requires: Version: @VERSION@ Libs: -L${libdir} -lgcell Cflags: -I${includedir} @DEFINES@ diff --git a/gnuradio-core/gnuradio-core.pc.in b/gnuradio-core/gnuradio-core.pc.in index dc06fcf8..9ff83504 100644 --- a/gnuradio-core/gnuradio-core.pc.in +++ b/gnuradio-core/gnuradio-core.pc.in @@ -5,7 +5,7 @@ includedir=@includedir@/gnuradio Name: gnuradio-core Description: GNU Software Radio toolkit -Requires: gruel fftw3f gsl gnuradio-omnithread +Requires: gruel fftw3f gsl Version: @VERSION@ Libs.private: @BOOST_LDFLAGS@ @BOOST_THREAD_LIB@ @BOOST_DATE_TIME_LIB@ Libs: -L${libdir} -lgnuradio-core diff --git a/omnithread/.gitignore b/omnithread/.gitignore deleted file mode 100644 index 5a51e3bc..00000000 --- a/omnithread/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -/Makefile -/Makefile.in -/.la -/.lo -/.deps -/.libs -/*.la -/*.lo -/gnuradio-omnithread.pc diff --git a/omnithread/Makefile.am b/omnithread/Makefile.am deleted file mode 100644 index 291cc8be..00000000 --- a/omnithread/Makefile.am +++ /dev/null @@ -1,71 +0,0 @@ -# -# Copyright 2003,2008 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -include $(top_srcdir)/Makefile.common - -SUBDIRS = gnuradio - -# This is the omnithread package, -# extracted from the omniORB-4.0.1 distribution - -# we should do some configure hacking to determine these on the fly -OMNITHREAD_DEFINES = -DPthreadDraftVersion=10 - -AM_CPPFLAGS = $(DEFINES) $(OMNITHREAD_DEFINES) $(OMNITHREAD_INCLUDES) \ - $(WITH_INCLUDES) - -# we call it libgromnithread to avoid a collision with libomnithread on Debian -lib_LTLIBRARIES = libgromnithread.la - -# At this point we only support the posix and nt pthreads i/f... - -if OMNITHREAD_POSIX -libgromnithread_la_SOURCES = \ - omni_time.cc \ - posix.cc -endif - -if OMNITHREAD_NT -libgromnithread_la_SOURCES = \ - omni_time.cc \ - nt.cc -endif - -libgromnithread_la_LDFLAGS = $(NO_UNDEFINED) - -libgromnithread_la_LIBADD = \ - $(PTHREAD_LIBS) - -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = gnuradio-omnithread.pc - -# ... but this code also came with the package - -EXTRA_DIST = \ - gnuradio-omnithread.pc.in \ - mach.cc \ - nt.cc \ - posix.cc \ - solaris.cc \ - threaddata.cc \ - vxWorks.cc \ - dir.mk \ - README diff --git a/omnithread/README b/omnithread/README deleted file mode 100644 index 1943d0ed..00000000 --- a/omnithread/README +++ /dev/null @@ -1,2 +0,0 @@ -The code in this directory is deprecated, please use the Boost thread -library for new code. diff --git a/omnithread/dir.mk b/omnithread/dir.mk deleted file mode 100644 index d5380341..00000000 --- a/omnithread/dir.mk +++ /dev/null @@ -1,229 +0,0 @@ -ifeq ($(ThreadSystem),Solaris) -CXXSRCS = solaris.cc -DIR_CPPFLAGS = $(OMNITHREAD_CPPFLAGS) -endif - -ifeq ($(ThreadSystem),Posix) -CXXSRCS = posix.cc -DIR_CPPFLAGS = $(OMNITHREAD_CPPFLAGS) $(OMNITHREAD_POSIX_CPPFLAGS) -endif - -ifeq ($(ThreadSystem),NT) -CXXSRCS = nt.cc -DIR_CPPFLAGS = $(OMNITHREAD_CPPFLAGS) -MSVC_STATICLIB_CXXNODEBUGFLAGS += -D_WINSTATIC -MSVC_STATICLIB_CXXDEBUGFLAGS += -D_WINSTATIC -MSVC_DLL_CXXNODEBUGFLAGS += -D_OMNITHREAD_DLL -MSVC_DLL_CXXDEBUGFLAGS += -D_OMNITHREAD_DLL -endif - -ifeq ($(ThreadSystem),NTPosix) -CXXSRCS = posix.cc -DIR_CPPFLAGS = $(OMNITHREAD_CPPFLAGS) -MSVC_STATICLIB_CXXNODEBUGFLAGS += -D_WINSTATIC -MSVC_STATICLIB_CXXDEBUGFLAGS += -D_WINSTATIC -MSVC_DLL_CXXNODEBUGFLAGS += -D_OMNITHREAD_DLL -MSVC_DLL_CXXDEBUGFLAGS += -D_OMNITHREAD_DLL -endif - -ifeq ($(ThreadSystem),Mach) -CXXSRCS = mach.cc -DIR_CPPFLAGS = $(OMNITHREAD_CPPFLAGS) -endif - -ifeq ($(ThreadSystem),vxWorks) -CXXSRCS = vxWorks.cc -OBJS = vxWorks.o -DIR_CPPFLAGS = $(OMNITHREAD_CPPFLAGS) -endif - -LIB_NAME := omnithread -LIB_VERSION := $(OMNITHREAD_VERSION) -LIB_OBJS := $(CXXSRCS:.cc=.o) -LIB_IMPORTS := $(OMNITHREAD_PLATFORM_LIB) - -all:: mkstatic mkshared - -export:: mkstatic mkshared - -ifdef INSTALLTARGET -install:: mkstatic mkshared -endif - -vers := $(subst ., ,$(LIB_VERSION)) -ifeq ($(words $(vers)), 2) - vers := _ $(vers) - major := "" -else - major := $(word 1, $(vers)) -endif - -namespec := $(LIB_NAME) $(vers) - -############################################################################## -# Build Static library -############################################################################## - -ifndef NoStaticLibrary - -staticlib := static/$(patsubst %,$(LibNoDebugPattern),$(LIB_NAME)$(major)) - -mkstatic:: - @(dir=static; $(CreateDir)) - -mkstatic:: $(staticlib) - -$(staticlib): $(patsubst %, static/%, $(LIB_OBJS)) - @$(StaticLinkLibrary) - -export:: $(staticlib) - @$(ExportLibrary) - -ifdef INSTALLTARGET -install:: $(staticlib) - @$(InstallLibrary) -endif - -clean:: - $(RM) static/*.o - $(RM) $(staticlib) - -veryclean:: - $(RM) static/*.o - $(RM) $(staticlib) - -else - -mkstatic:: - -endif - - -############################################################################## -# Build Shared library -############################################################################## -ifdef BuildSharedLibrary - -shlib := shared/$(shell $(SharedLibraryFullName) $(namespec)) - -ifdef Win32Platform -# in case of Win32 lossage: - imps := $(patsubst $(DLLDebugSearchPattern),$(DLLNoDebugSearchPattern), \ - $(LIB_IMPORTS)) -else - imps := $(LIB_IMPORTS) -endif - -mkshared:: - @(dir=shared; $(CreateDir)) - -mkshared:: $(shlib) - -$(shlib): $(patsubst %, shared/%, $(LIB_OBJS)) - @(namespec="$(namespec)" extralibs="$(imps)" nodeffile=1; \ - $(MakeCXXSharedLibrary)) - -export:: $(shlib) - @(namespec="$(namespec)"; \ - $(ExportSharedLibrary)) - -ifdef INSTALLTARGET -install:: $(shlib) - @(namespec="$(namespec)"; \ - $(InstallSharedLibrary)) -endif - -clean:: - $(RM) shared/*.o - (dir=shared; $(CleanSharedLibrary)) - -veryclean:: - $(RM) shared/*.o - @(dir=shared; $(CleanSharedLibrary)) - -else - -mkshared:: - -endif - -############################################################################## -# Build debug libraries for Win32 -############################################################################## -ifdef Win32Platform - -ifdef BuildSharedLibrary - -all:: mkstaticdbug mkshareddbug - -export:: mkstaticdbug mkshareddbug - -else - -all:: mkstaticdbug - -export:: mkstaticdbug - -endif - - -##################################################### -# Static debug libraries -##################################################### - -dbuglib := debug/$(patsubst %,$(LibDebugPattern),$(LIB_NAME)$(major)) - -mkstaticdbug:: - @(dir=debug; $(CreateDir)) - -mkstaticdbug:: $(dbuglib) - -$(dbuglib): $(patsubst %, debug/%, $(LIB_OBJS)) - @$(StaticLinkLibrary) - -export:: $(dbuglib) - @$(ExportLibrary) - -clean:: - $(RM) debug/*.o - $(RM) $(dbuglib) - -veryclean:: - $(RM) debug/*.o - $(RM) $(dbuglib) - -##################################################### -# DLL debug libraries -##################################################### - -ifdef BuildSharedLibrary - -dbugshlib := shareddebug/$(shell $(SharedLibraryDebugFullName) $(namespec)) - -dbugimps := $(patsubst $(DLLNoDebugSearchPattern),$(DLLDebugSearchPattern), \ - $(LIB_IMPORTS)) - -mkshareddbug:: - @(dir=shareddebug; $(CreateDir)) - -mkshareddbug:: $(dbugshlib) - -$(dbugshlib): $(patsubst %, shareddebug/%, $(LIB_OBJS)) - (namespec="$(namespec)" debug=1 extralibs="$(dbugimps)" nodeffile=1; \ - $(MakeCXXSharedLibrary)) - -export:: $(dbugshlib) - @(namespec="$(namespec)" debug=1; \ - $(ExportSharedLibrary)) - -clean:: - $(RM) shareddebug/*.o - @(dir=shareddebug; $(CleanSharedLibrary)) - -veryclean:: - $(RM) shareddebug/*.o - @(dir=shareddebug; $(CleanSharedLibrary)) - -endif -endif - diff --git a/omnithread/gnuradio-omnithread.pc.in b/omnithread/gnuradio-omnithread.pc.in deleted file mode 100644 index 0a94562e..00000000 --- a/omnithread/gnuradio-omnithread.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@/gnuradio - -Name: gnuradio-omnithread -Description: The GNU Radio omniORB threading library -Requires: -Version: @VERSION@ -Libs: -L${libdir} -lgromnithread -Cflags: -I${includedir} @DEFINES@ @PTHREAD_CFLAGS@ diff --git a/omnithread/gnuradio/.gitignore b/omnithread/gnuradio/.gitignore deleted file mode 100644 index b336cc7c..00000000 --- a/omnithread/gnuradio/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/Makefile -/Makefile.in diff --git a/omnithread/gnuradio/Makefile.am b/omnithread/gnuradio/Makefile.am deleted file mode 100644 index 1ec56129..00000000 --- a/omnithread/gnuradio/Makefile.am +++ /dev/null @@ -1,32 +0,0 @@ -# -# Copyright 2009 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -include $(top_srcdir)/Makefile.common - -grinclude_HEADERS = \ - omnithread.h \ - omni_time.h \ - ot_mach.h \ - ot_nt.h \ - ot_posix.h \ - ot_pthread_nt.h \ - ot_solaris.h \ - ot_VxThread.h diff --git a/omnithread/gnuradio/omni_time.h b/omnithread/gnuradio/omni_time.h deleted file mode 100644 index bfb15161..00000000 --- a/omnithread/gnuradio/omni_time.h +++ /dev/null @@ -1,89 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007,2008 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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 3, or (at your option) - * any later version. - * - * GNU Radio 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef INCLUDED_OMNI_TIME_H -#define INCLUDED_OMNI_TIME_H - -struct omni_time { - long int d_secs; // seconds. - long int d_nsecs; // nanoseconds. Always in [0, 1e9-1] - - omni_time() : d_secs(0), d_nsecs(0) {} - omni_time(long secs, long nanosecs=0) : d_secs(secs), d_nsecs(nanosecs) {} - - // N.B., this only makes sense for differences between times. - // Double doesn't have enough bits to precisely represent an absolute time. - omni_time(double secs); - - // N.B. This only makes sense for differences between times. - // Double doesn't have enough bits to precisely represent an absolute time. - double double_time() const { return (double)d_secs + d_nsecs * 1e-9; } - - /*! - * \brief Return an absolute time suitable for use with - * schedule_one_shot_timeout & schedule_periodic_timeout - * - * The return value is the current time plus the given relative offset. - */ - static omni_time time(const omni_time &relative_offset = omni_time()); -}; - - -inline static bool -operator<(const omni_time &x, const omni_time &y) -{ - return ((x.d_secs < y.d_secs) - || (x.d_secs == y.d_secs && x.d_nsecs < y.d_nsecs)); -} - -inline static bool -operator>(const omni_time &x, const omni_time &y) -{ - return ((x.d_secs > y.d_secs) - || (x.d_secs == y.d_secs && x.d_nsecs > y.d_nsecs)); -} - -inline static bool -operator>=(const omni_time &x, const omni_time &y) -{ - return ((x.d_secs > y.d_secs) - || (x.d_secs == y.d_secs && x.d_nsecs >= y.d_nsecs)); -} - -inline static bool -operator<=(const omni_time &x, const omni_time &y) -{ - return ((x.d_secs < y.d_secs) - || (x.d_secs == y.d_secs && x.d_nsecs <= y.d_nsecs)); -} - -inline static bool -operator==(const omni_time &x, const omni_time &y) -{ - return (x.d_secs == y.d_secs && x.d_nsecs == y.d_nsecs); -} - - -omni_time operator+(const omni_time &x, const omni_time &y); -omni_time operator+(const omni_time &x, double y); -omni_time operator-(const omni_time &x, const omni_time &y); -omni_time operator-(const omni_time &x, double y); - -#endif /* INCLUDED_OMNI_TIME_H */ diff --git a/omnithread/gnuradio/omnithread.h b/omnithread/gnuradio/omnithread.h deleted file mode 100644 index 8e8162b1..00000000 --- a/omnithread/gnuradio/omnithread.h +++ /dev/null @@ -1,626 +0,0 @@ -// -*- Mode: C++; -*- -// Package : omnithread -// omnithread.h Created : 7/94 tjr -// -// Copyright (C) 2006 Free Software Foundation, Inc. -// Copyright (C) 1994,1995,1996, 1997 Olivetti & Oracle Research Laboratory -// -// This file is part of the omnithread library -// -// The omnithread library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library 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 -// Library General Public License for more details. -// -// You should have received a copy of the GNU Library General Public -// License along with this library; if not, write to the Free -// Software Foundation, Inc., 51 Franklin Street, Boston, MA -// 02110-1301, USA -// - -// -// Interface to OMNI thread abstraction. -// -// This file declares classes for threads and synchronisation objects -// (mutexes, condition variables and counting semaphores). -// -// Wherever a seemingly arbitrary choice has had to be made as to the interface -// provided, the intention here has been to be as POSIX-like as possible. This -// is why there is no semaphore timed wait, for example. -// - -#ifndef __omnithread_h_ -#define __omnithread_h_ - -#ifndef NULL -#define NULL 0 -#endif - -class omni_mutex; -class omni_condition; -class omni_semaphore; -class omni_thread; - -// -// OMNI_THREAD_EXPOSE can be defined as public or protected to expose the -// implementation class - this may be useful for debugging. Hopefully this -// won't change the underlying structure which the compiler generates so that -// this can work without recompiling the library. -// - -#ifndef OMNI_THREAD_EXPOSE -#define OMNI_THREAD_EXPOSE private -#endif - -// -// Include implementation-specific header file. -// -// This must define 4 CPP macros of the form OMNI_x_IMPLEMENTATION for mutex, -// condition variable, semaphore and thread. Each should define any -// implementation-specific members of the corresponding classes. -// - - -// -// For now, we assume they've always got a Posix Threads implementation. -// If not, it'll take some configure hacking to sort it out, along with -// the relevant libraries to link with, etc. -// - -#if !defined(OMNITHREAD_POSIX) && !defined(OMNITHREAD_NT) && defined HAVE_CONFIG_H -// #include // No, No, No! Never include from a header -#endif - -#if defined(OMNITHREAD_POSIX) -#include - -#elif defined(OMNITHREAD_NT) -#include - -#ifdef _MSC_VER - -// Using MSVC++ to compile. If compiling library as a DLL, -// define _OMNITHREAD_DLL. If compiling as a statuc library, define -// _WINSTATIC -// If compiling an application that is to be statically linked to omnithread, -// define _WINSTATIC (if the application is to be dynamically linked, -// there is no need to define any of these macros). - -#if defined (_OMNITHREAD_DLL) && defined(_WINSTATIC) -#error "Both _OMNITHREAD_DLL and _WINSTATIC are defined." -#elif defined(_OMNITHREAD_DLL) -#define _OMNITHREAD_NTDLL_ __declspec(dllexport) -#elif !defined(_WINSTATIC) -#define _OMNITHREAD_NTDLL_ __declspec(dllimport) -#elif defined(_WINSTATIC) -#define _OMNITHREAD_NTDLL_ -#endif - // _OMNITHREAD_DLL && _WINSTATIC - -#else - -// Not using MSVC++ to compile -#define _OMNITHREAD_NTDLL_ - -#endif - // _MSC_VER - -#elif defined(__vxWorks__) -#include - -#elif defined(__sunos__) -#if __OSVERSION__ != 5 -// XXX Workaround for SUN C++ compiler (seen on 4.2) Template.DB code -// regeneration bug. See omniORB2/CORBA_sysdep.h for details. -#if !defined(__SUNPRO_CC) || __OSVERSION__ != '5' -#error "Only SunOS 5.x or later is supported." -#endif -#endif -#ifdef UseSolarisThreads -#include -#else -#include -#endif - -#elif defined(__rtems__) -#include -#include - -#elif defined(__macos__) -#include -#include - -#else -#error "No implementation header file" -#endif - - -#if !defined(__WIN32__) -#define _OMNITHREAD_NTDLL_ -#endif - -#if (!defined(OMNI_MUTEX_IMPLEMENTATION) || \ - !defined(OMNI_MUTEX_LOCK_IMPLEMENTATION) || \ - !defined(OMNI_MUTEX_TRYLOCK_IMPLEMENTATION)|| \ - !defined(OMNI_MUTEX_UNLOCK_IMPLEMENTATION) || \ - !defined(OMNI_CONDITION_IMPLEMENTATION) || \ - !defined(OMNI_SEMAPHORE_IMPLEMENTATION) || \ - !defined(OMNI_THREAD_IMPLEMENTATION)) -#error "Implementation header file incomplete" -#endif - - -// -// This exception is thrown in the event of a fatal error. -// - -class _OMNITHREAD_NTDLL_ omni_thread_fatal { -public: - int error; - omni_thread_fatal(int e = 0) : error(e) {} -}; - - -// -// This exception is thrown when an operation is invoked with invalid -// arguments. -// - -class _OMNITHREAD_NTDLL_ omni_thread_invalid {}; - - -/////////////////////////////////////////////////////////////////////////// -// -// Mutex -// -/////////////////////////////////////////////////////////////////////////// - -class _OMNITHREAD_NTDLL_ omni_mutex { - -public: - omni_mutex(void); - ~omni_mutex(void); - - inline void lock(void) { OMNI_MUTEX_LOCK_IMPLEMENTATION } - inline void unlock(void) { OMNI_MUTEX_UNLOCK_IMPLEMENTATION } - inline int trylock(void) { return OMNI_MUTEX_TRYLOCK_IMPLEMENTATION } - // if mutex is unlocked, lock it and return 1 (true). - // If it's already locked then return 0 (false). - - inline void acquire(void) { lock(); } - inline void release(void) { unlock(); } - // the names lock and unlock are preferred over acquire and release - // since we are attempting to be as POSIX-like as possible. - - friend class omni_condition; - -private: - // dummy copy constructor and operator= to prevent copying - omni_mutex(const omni_mutex&); - omni_mutex& operator=(const omni_mutex&); - -OMNI_THREAD_EXPOSE: - OMNI_MUTEX_IMPLEMENTATION -}; - -// -// As an alternative to: -// { -// mutex.lock(); -// ..... -// mutex.unlock(); -// } -// -// you can use a single instance of the omni_mutex_lock class: -// -// { -// omni_mutex_lock l(mutex); -// .... -// } -// -// This has the advantage that mutex.unlock() will be called automatically -// when an exception is thrown. -// - -class _OMNITHREAD_NTDLL_ omni_mutex_lock { - omni_mutex& mutex; -public: - omni_mutex_lock(omni_mutex& m) : mutex(m) { mutex.lock(); } - ~omni_mutex_lock(void) { mutex.unlock(); } -private: - // dummy copy constructor and operator= to prevent copying - omni_mutex_lock(const omni_mutex_lock&); - omni_mutex_lock& operator=(const omni_mutex_lock&); -}; - - -/////////////////////////////////////////////////////////////////////////// -// -// Condition variable -// -/////////////////////////////////////////////////////////////////////////// - -class _OMNITHREAD_NTDLL_ omni_condition { - - omni_mutex* mutex; - -public: - omni_condition(omni_mutex* m); - // constructor must be given a pointer to an existing mutex. The - // condition variable is then linked to the mutex, so that there is an - // implicit unlock and lock around wait() and timed_wait(). - - ~omni_condition(void); - - void wait(void); - // wait for the condition variable to be signalled. The mutex is - // implicitly released before waiting and locked again after waking up. - // If wait() is called by multiple threads, a signal may wake up more - // than one thread. See POSIX threads documentation for details. - - int timedwait(unsigned long secs, unsigned long nanosecs = 0); - // timedwait() is given an absolute time to wait until. To wait for a - // relative time from now, use omni_thread::get_time. See POSIX threads - // documentation for why absolute times are better than relative. - // Returns 1 (true) if successfully signalled, 0 (false) if time - // expired. - - void signal(void); - // if one or more threads have called wait(), signal wakes up at least - // one of them, possibly more. See POSIX threads documentation for - // details. - - void broadcast(void); - // broadcast is like signal but wakes all threads which have called - // wait(). - -private: - // dummy copy constructor and operator= to prevent copying - omni_condition(const omni_condition&); - omni_condition& operator=(const omni_condition&); - -OMNI_THREAD_EXPOSE: - OMNI_CONDITION_IMPLEMENTATION -}; - - -/////////////////////////////////////////////////////////////////////////// -// -// Counting (or binary) semaphore -// -/////////////////////////////////////////////////////////////////////////// - -class _OMNITHREAD_NTDLL_ omni_semaphore { - -public: - // if max_count == 1, you've got a binary semaphore. - omni_semaphore(unsigned int initial = 1, unsigned int max_count = 0x7fffffff); - ~omni_semaphore(void); - - void wait(void); - // if semaphore value is > 0 then decrement it and carry on. If it's - // already 0 then block. - - int trywait(void); - // if semaphore value is > 0 then decrement it and return 1 (true). - // If it's already 0 then return 0 (false). - - void post(void); - // if any threads are blocked in wait(), wake one of them up. Otherwise - // increment the value of the semaphore. - -private: - // dummy copy constructor and operator= to prevent copying - omni_semaphore(const omni_semaphore&); - omni_semaphore& operator=(const omni_semaphore&); - -OMNI_THREAD_EXPOSE: - OMNI_SEMAPHORE_IMPLEMENTATION -}; - -// -// A helper class for semaphores, similar to omni_mutex_lock above. -// - -class _OMNITHREAD_NTDLL_ omni_semaphore_lock { - omni_semaphore& sem; -public: - omni_semaphore_lock(omni_semaphore& s) : sem(s) { sem.wait(); } - ~omni_semaphore_lock(void) { sem.post(); } -private: - // dummy copy constructor and operator= to prevent copying - omni_semaphore_lock(const omni_semaphore_lock&); - omni_semaphore_lock& operator=(const omni_semaphore_lock&); -}; - - -/////////////////////////////////////////////////////////////////////////// -// -// Thread -// -/////////////////////////////////////////////////////////////////////////// - -class _OMNITHREAD_NTDLL_ omni_thread { - -public: - - enum priority_t { - PRIORITY_LOW, - PRIORITY_NORMAL, - PRIORITY_HIGH - }; - - enum state_t { - STATE_NEW, // thread object exists but thread hasn't - // started yet. - STATE_RUNNING, // thread is running. - STATE_TERMINATED // thread has terminated but storage has not - // been reclaimed (i.e. waiting to be joined). - }; - - // - // Constructors set up the thread object but the thread won't start until - // start() is called. The create method can be used to construct and start - // a thread in a single call. - // - - omni_thread(void (*fn)(void*), void* arg = NULL, - priority_t pri = PRIORITY_NORMAL); - omni_thread(void* (*fn)(void*), void* arg = NULL, - priority_t pri = PRIORITY_NORMAL); - // these constructors create a thread which will run the given function - // when start() is called. The thread will be detached if given a - // function with void return type, undetached if given a function - // returning void*. If a thread is detached, storage for the thread is - // reclaimed automatically on termination. Only an undetached thread - // can be joined. - - void start(void); - // start() causes a thread created with one of the constructors to - // start executing the appropriate function. - -protected: - - omni_thread(void* arg = NULL, priority_t pri = PRIORITY_NORMAL); - // this constructor is used in a derived class. The thread will - // execute the run() or run_undetached() member functions depending on - // whether start() or start_undetached() is called respectively. - -public: - - void start_undetached(void); - // can be used with the above constructor in a derived class to cause - // the thread to be undetached. In this case the thread executes the - // run_undetached member function. - -protected: - - virtual ~omni_thread(void); - // destructor cannot be called by user (except via a derived class). - // Use exit() or cancel() instead. This also means a thread object must - // be allocated with new - it cannot be statically or automatically - // allocated. The destructor of a class that inherits from omni_thread - // shouldn't be public either (otherwise the thread object can be - // destroyed while the underlying thread is still running). - -public: - - void join(void**); - // join causes the calling thread to wait for another's completion, - // putting the return value in the variable of type void* whose address - // is given (unless passed a null pointer). Only undetached threads - // may be joined. Storage for the thread will be reclaimed. - - void set_priority(priority_t); - // set the priority of the thread. - - static omni_thread* create(void (*fn)(void*), void* arg = NULL, - priority_t pri = PRIORITY_NORMAL); - static omni_thread* create(void* (*fn)(void*), void* arg = NULL, - priority_t pri = PRIORITY_NORMAL); - // create spawns a new thread executing the given function with the - // given argument at the given priority. Returns a pointer to the - // thread object. It simply constructs a new thread object then calls - // start. - - static void exit(void* return_value = NULL); - // causes the calling thread to terminate. - - static omni_thread* self(void); - // returns the calling thread's omni_thread object. If the - // calling thread is not the main thread and is not created - // using this library, returns 0. (But see create_dummy() - // below.) - - static void yield(void); - // allows another thread to run. - - static void sleep(unsigned long secs, unsigned long nanosecs = 0); - // sleeps for the given time. - - static void get_time(unsigned long* abs_sec, unsigned long* abs_nsec, - unsigned long rel_sec = 0, unsigned long rel_nsec=0); - // calculates an absolute time in seconds and nanoseconds, suitable for - // use in timed_waits on condition variables, which is the current time - // plus the given relative offset. - - - static void stacksize(unsigned long sz); - static unsigned long stacksize(); - // Use this value as the stack size when spawning a new thread. - // The default value (0) means that the thread library default is - // to be used. - - - // Per-thread data - // - // These functions allow you to attach additional data to an - // omni_thread. First allocate a key for yourself with - // allocate_key(). Then you can store any object whose class is - // derived from value_t. Any values still stored in the - // omni_thread when the thread exits are deleted. - // - // These functions are NOT thread safe, so you should be very - // careful about setting/getting data in a different thread to the - // current thread. - - typedef unsigned int key_t; - static key_t allocate_key(); - - class value_t { - public: - virtual ~value_t() {} - }; - - value_t* set_value(key_t k, value_t* v); - // Sets a value associated with the given key. The key must - // have been allocated with allocate_key(). If a value has - // already been set with the specified key, the old value_t - // object is deleted and replaced. Returns the value which was - // set, or zero if the key is invalid. - - value_t* get_value(key_t k); - // Returns the value associated with the key. If the key is - // invalid, or there is no value for the key, returns zero. - - value_t* remove_value(key_t k); - // Removes the value associated with the key and returns it. - // If the key is invalid, or there is no value for the key, - // returns zero. - - - // Dummy omni_thread - // - // Sometimes, an application finds itself with threads created - // outside of omnithread which must interact with omnithread - // features such as the per-thread data. In this situation, - // omni_thread::self() would normally return 0. These functions - // allow the application to create a suitable dummy omni_thread - // object. - - static omni_thread* create_dummy(void); - // creates a dummy omni_thread for the calling thread. Future - // calls to self() will return the dummy omni_thread. Throws - // omni_thread_invalid if this thread already has an - // associated omni_thread (real or dummy). - - static void release_dummy(); - // release the dummy omni_thread for this thread. This - // function MUST be called before the thread exits. Throws - // omni_thread_invalid if the calling thread does not have a - // dummy omni_thread. - - // class ensure_self should be created on the stack. If created in - // a thread without an associated omni_thread, it creates a dummy - // thread which is released when the ensure_self object is deleted. - - class ensure_self { - public: - inline ensure_self() : _dummy(0) - { - _self = omni_thread::self(); - if (!_self) { - _dummy = 1; - _self = omni_thread::create_dummy(); - } - } - inline ~ensure_self() - { - if (_dummy) - omni_thread::release_dummy(); - } - inline omni_thread* self() { return _self; } - private: - omni_thread* _self; - int _dummy; - }; - - -private: - - virtual void run(void* /*arg*/) {} - virtual void* run_undetached(void* /*arg*/) { return NULL; } - // can be overridden in a derived class. When constructed using the - // the constructor omni_thread(void*, priority_t), these functions are - // called by start() and start_undetached() respectively. - - void common_constructor(void* arg, priority_t pri, int det); - // implements the common parts of the constructors. - - omni_mutex mutex; - // used to protect any members which can change after construction, - // i.e. the following 2 members. - - state_t _state; - priority_t _priority; - - static omni_mutex* next_id_mutex; - static int next_id; - int _id; - - void (*fn_void)(void*); - void* (*fn_ret)(void*); - void* thread_arg; - int detached; - int _dummy; - value_t** _values; - unsigned long _value_alloc; - - omni_thread(const omni_thread&); - omni_thread& operator=(const omni_thread&); - // Not implemented - -public: - - priority_t priority(void) { - - // return this thread's priority. - - omni_mutex_lock l(mutex); - return _priority; - } - - state_t state(void) { - - // return thread state (invalid, new, running or terminated). - - omni_mutex_lock l(mutex); - return _state; - } - - int id(void) { return _id; } - // return unique thread id within the current process. - - - // This class plus the instance of it declared below allows us to execute - // some initialisation code before main() is called. - - class _OMNITHREAD_NTDLL_ init_t { - public: - init_t(void); - ~init_t(void); - }; - - friend class init_t; - friend class omni_thread_dummy; - -OMNI_THREAD_EXPOSE: - OMNI_THREAD_IMPLEMENTATION -}; - -#ifndef __rtems__ -static omni_thread::init_t omni_thread_init; -#else -// RTEMS calls global Ctor/Dtor in a context that is not -// a posix thread. Calls to functions to pthread_self() in -// that context returns NULL. -// So, for RTEMS we will make the thread initialization at the -// beginning of the Init task that has a posix context. -#endif - -#endif diff --git a/omnithread/gnuradio/ot_VxThread.h b/omnithread/gnuradio/ot_VxThread.h deleted file mode 100644 index e96c036c..00000000 --- a/omnithread/gnuradio/ot_VxThread.h +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef __VXTHREAD_H__ -#define __VXTHREAD_H__ -/* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% Project: omniORB -%% Filename: $Filename$ -%% Author: Guillaume/Bill ARRECKX -%% Copyright Wavetek Wandel & Goltermann, Plymouth. -%% Description: OMNI thread implementation classes for VxWorks threads -%% Notes: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% $Log$ -%% Revision 1.1 2004/04/10 18:00:52 eb -%% Initial revision -%% -%% Revision 1.1.1.1 2004/03/01 00:20:27 eb -%% initial checkin -%% -%% Revision 1.1 2003/05/25 05:29:04 eb -%% see ChangeLog -%% -%% Revision 1.1.2.1 2003/02/17 02:03:07 dgrisby -%% vxWorks port. (Thanks Michael Sturm / Acterna Eningen GmbH). -%% -%% Revision 1.1.1.1 2002/11/19 14:55:21 sokcevti -%% OmniOrb4.0.0 VxWorks port -%% -%% Revision 1.2 2002/06/14 12:45:50 engeln -%% unnecessary members in condition removed. -%% --- -%% -%% Revision 1.1.1.1 2002/04/02 10:08:49 sokcevti -%% omniORB4 initial realease -%% -%% Revision 1.1 2001/03/23 16:50:23 hartmut -%% Initial Version 2.8 -%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -*/ - - -/////////////////////////////////////////////////////////////////////////// -// Includes -/////////////////////////////////////////////////////////////////////////// -#include -#include -#include - - -/////////////////////////////////////////////////////////////////////////// -// Externs prototypes -/////////////////////////////////////////////////////////////////////////// -extern "C" void omni_thread_wrapper(void* ptr); - - -/////////////////////////////////////////////////////////////////////////// -// Exported macros -// Note: These are added as private members in each class implementation. -/////////////////////////////////////////////////////////////////////////// -#define OMNI_MUTEX_IMPLEMENTATION \ - SEM_ID mutexID; \ - bool m_bConstructed; - -#define OMNI_CONDITION_IMPLEMENTATION \ - long waiters_; \ - SEM_ID waiters_lock_; \ - SEM_ID sema_; - -#define OMNI_SEMAPHORE_IMPLEMENTATION \ - SEM_ID semID; - -#define OMNI_MUTEX_LOCK_IMPLEMENTATION \ - if(semTake(mutexID, WAIT_FOREVER) != OK) \ - { \ - throw omni_thread_fatal(errno); \ - } - -#define OMNI_MUTEX_UNLOCK_IMPLEMENTATION \ - if(semGive(mutexID) != OK) \ - { \ - throw omni_thread_fatal(errno); \ - } - -#define OMNI_THREAD_IMPLEMENTATION \ - friend void omni_thread_wrapper(void* ptr); \ - static int vxworks_priority(priority_t); \ - omni_condition *running_cond; \ - void* return_val; \ - int tid; \ - public: \ - static void attach(void); \ - static void detach(void); \ - static void show(void); - - -/////////////////////////////////////////////////////////////////////////// -// Porting macros -/////////////////////////////////////////////////////////////////////////// -// This is a wrapper function for the 'main' function which does not exists -// as such in VxWorks. The wrapper creates a launch function instead, -// which spawns the application wrapped in a omni_thread. -// Argc will always be null. -/////////////////////////////////////////////////////////////////////////// -#define main( discarded_argc, discarded_argv ) \ - omni_discard_retval() \ - { \ - throw; \ - } \ - int omni_main( int argc, char **argv ); \ - void launch( ) \ - { \ - omni_thread* th = new omni_thread( (void(*)(void*))omni_main );\ - th->start();\ - }\ - int omni_main( int argc, char **argv ) - - -#endif // ndef __VXTHREAD_H__ diff --git a/omnithread/gnuradio/ot_mach.h b/omnithread/gnuradio/ot_mach.h deleted file mode 100644 index 76361926..00000000 --- a/omnithread/gnuradio/ot_mach.h +++ /dev/null @@ -1,51 +0,0 @@ -// Package : omnithread -// omnithread/posix.h Created : 7/97 lars immisch lars@ibp.de -// -// Copyright (C) 1994,1995,1996, 1997 Immisch, becker & Partner -// -// This file is part of the omnithread library -// -// The omnithread library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library 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 -// Library General Public License for more details. -// -// You should have received a copy of the GNU Library General Public -// License along with this library; if not, write to the Free -// Software Foundation, Inc., 51 Franklin Street, Boston, MA -// 02110-1301, USA -// -// -// OMNI thread implementation classes for posix threads -// - -#ifndef __omnithread_mach_h_ -#define __omnithread_mach_h_ - -#include - -extern "C" void* omni_thread_wrapper(void* ptr); - -#define OMNI_MUTEX_IMPLEMENTATION \ - struct mutex mach_mutex; - -#define OMNI_CONDITION_IMPLEMENTATION \ - struct condition mach_cond; - -#define OMNI_SEMAPHORE_IMPLEMENTATION \ - omni_mutex m; \ - omni_condition c; \ - int value; - - -#define OMNI_THREAD_IMPLEMENTATION \ - cthread_t mach_thread; \ - static int mach_priority(priority_t); \ - friend void* omni_thread_wrapper(void* ptr); - -#endif diff --git a/omnithread/gnuradio/ot_nt.h b/omnithread/gnuradio/ot_nt.h deleted file mode 100644 index 551ccf2f..00000000 --- a/omnithread/gnuradio/ot_nt.h +++ /dev/null @@ -1,85 +0,0 @@ -// Package : omnithread -// omnithread/nt.h Created : 6/95 tjr -// -// Copyright (C) 1995, 1996, 1997 Olivetti & Oracle Research Laboratory -// -// This file is part of the omnithread library -// -// The omnithread library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library 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 -// Library General Public License for more details. -// -// You should have received a copy of the GNU Library General Public -// License along with this library; if not, write to the Free -// Software Foundation, Inc., 51 Franklin Street, Boston, MA -// 02110-1301, USA -// -// -// OMNI thread implementation classes for NT threads. -// - -#ifndef __omnithread_nt_h_ -#define __omnithread_nt_h_ - -#ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# define OMNI_DEFINED_WIN32_LEAN_AND_MEAN -#endif - -#include - -#ifdef OMNI_DEFINED_WIN32_LEAN_AND_MEAN -# undef WIN32_LEAN_AND_MEAN -# undef OMNI_DEFINED_WIN32_LEAN_AND_MEAN -#endif - - -#ifndef __BCPLUSPLUS__ -#define OMNI_THREAD_WRAPPER \ - unsigned __stdcall omni_thread_wrapper(LPVOID ptr); -#else -#define OMNI_THREAD_WRAPPER \ - void _USERENTRY omni_thread_wrapper(void *ptr); -#endif - -extern "C" OMNI_THREAD_WRAPPER; - -#define OMNI_MUTEX_IMPLEMENTATION \ - CRITICAL_SECTION crit; - -#define OMNI_MUTEX_LOCK_IMPLEMENTATION \ - EnterCriticalSection(&crit); - -#define OMNI_MUTEX_TRYLOCK_IMPLEMENTATION \ - TryEnterCriticalSection(&crit); - -#define OMNI_MUTEX_UNLOCK_IMPLEMENTATION \ - LeaveCriticalSection(&crit); - -#define OMNI_CONDITION_IMPLEMENTATION \ - CRITICAL_SECTION crit; \ - omni_thread* waiting_head; \ - omni_thread* waiting_tail; - -#define OMNI_SEMAPHORE_IMPLEMENTATION \ - HANDLE nt_sem; - -#define OMNI_THREAD_IMPLEMENTATION \ - HANDLE handle; \ - DWORD nt_id; \ - void* return_val; \ - HANDLE cond_semaphore; \ - omni_thread* cond_next; \ - omni_thread* cond_prev; \ - BOOL cond_waiting; \ - static int nt_priority(priority_t); \ - friend class omni_condition; \ - friend OMNI_THREAD_WRAPPER; - -#endif diff --git a/omnithread/gnuradio/ot_posix.h b/omnithread/gnuradio/ot_posix.h deleted file mode 100644 index 666ccc08..00000000 --- a/omnithread/gnuradio/ot_posix.h +++ /dev/null @@ -1,81 +0,0 @@ -// Package : omnithread -// omnithread/posix.h Created : 7/94 tjr -// -// Copyright (C) 2006 Free Software Foundation, Inc. -// Copyright (C) 1994,1995,1996, 1997 Olivetti & Oracle Research Laboratory -// -// This file is part of the omnithread library -// -// The omnithread library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library 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 -// Library General Public License for more details. -// -// You should have received a copy of the GNU Library General Public -// License along with this library; if not, write to the Free -// Software Foundation, Inc., 51 Franklin Street, Boston, MA -// 02110-1301, USA -// -// -// OMNI thread implementation classes for posix threads -// - -#ifndef __omnithread_posix_h_ -#define __omnithread_posix_h_ - -#if defined(__alpha__) && defined(__osf1__) || defined(__hpux__) -// stop unnecessary definitions of TRY, etc on OSF -#ifndef EXC_HANDLING -#define EXC_HANDLING -#endif -#endif - -#ifndef __POSIX_NT__ -# include -#else -# ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# define OMNI_DEFINED_WIN32_LEAN_AND_MEAN -# endif -# include -# include "pthread_nt.h" -# ifdef OMNI_DEFINED_WIN32_LEAN_AND_MEAN -# undef WIN32_LEAN_AND_MEAN -# undef OMNI_DEFINED_WIN32_LEAN_AND_MEAN -# endif -#endif - -extern "C" void* omni_thread_wrapper(void* ptr); - -#define OMNI_MUTEX_IMPLEMENTATION \ - pthread_mutex_t posix_mutex; - -#define OMNI_MUTEX_LOCK_IMPLEMENTATION \ - pthread_mutex_lock(&posix_mutex); - -#define OMNI_MUTEX_TRYLOCK_IMPLEMENTATION \ - (pthread_mutex_trylock(&posix_mutex)==0); - -#define OMNI_MUTEX_UNLOCK_IMPLEMENTATION \ - pthread_mutex_unlock(&posix_mutex); - -#define OMNI_CONDITION_IMPLEMENTATION \ - pthread_cond_t posix_cond; - -#define OMNI_SEMAPHORE_IMPLEMENTATION \ - omni_mutex m; \ - omni_condition c; \ - int value; \ - int max_count; - -#define OMNI_THREAD_IMPLEMENTATION \ - pthread_t posix_thread; \ - static int posix_priority(priority_t); \ - friend void* omni_thread_wrapper(void* ptr); - -#endif diff --git a/omnithread/gnuradio/ot_pthread_nt.h b/omnithread/gnuradio/ot_pthread_nt.h deleted file mode 100644 index 324b5257..00000000 --- a/omnithread/gnuradio/ot_pthread_nt.h +++ /dev/null @@ -1,186 +0,0 @@ -/* Package : omnithread - omnithread/pthread_nt.h Created : Steven Brenneis - - Copyright (C) 1998 Steven Brennes - - This file is part of the omnithread library - - The omnithread library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 51 Franklin Street, Boston, MA - 02110-1301, USA - - Posix Threads implementation for Windows NT, version 4.0 -*/ - -#ifndef PTHREAD_NT_H_INCLUDED -#define PTHREAD_NT_H_INCLUDED - -#include - -#ifndef ETIMEDOUT -// May have to be changed if NT starts supporting more errno values -#define ETIMEDOUT 60 -#endif - -#undef PthreadDraftVersion -#define PthreadDraftVersion 10 - -#define NoNanoSleep - -#define PthreadSupportThreadPriority - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _TIMERS_T_ -#define _TIMERS_T_ - typedef struct timespec { - unsigned long tv_sec; - long tv_nsec; - } timespec_t; -#endif - -typedef char* __pthreadLongString_t; -typedef void* __pthreadLongAddr_t; -typedef __pthreadLongAddr_t* __pthreadLongAddr_p; -typedef long __pthreadLongInt_t; -typedef unsigned long __pthreadLongUint_t; -typedef __pthreadLongAddr_p __pthreadTsd_t; - -typedef struct __pthread_mutex_t { - unsigned int lock; /* LOCK, SLOW, TYPE, RECURSIVE */ - unsigned int valid; /* Validation info */ - __pthreadLongString_t name; /* Name of mutex */ - unsigned int arg; /* printf argument for name */ - unsigned int depth; /* Recursive lock depth */ - unsigned long sequence; /* Mutex sequence number */ - unsigned long owner; /* Current owner (if known */ - __pthreadLongAddr_t block; /* Pointer to blocking struct */ -} pthread_mutex_t; - -typedef struct __pthread_mutexattr_t { - long valid; - __pthreadLongUint_t reserved[15]; -} pthread_mutexattr_t; - -typedef struct __pthread_cond_t { - unsigned int state; /* EVENT, SLOW, REFCNT */ - unsigned int valid; /* Validation info */ - __pthreadLongString_t name; /* Name of condition variable */ - unsigned int arg; /* printf argument for name */ - unsigned long sequence; /* Condition variable seq # */ - __pthreadLongAddr_t block; /* Pointer to blocking struct */ -} pthread_cond_t ; - -typedef struct __pthread_condattr_t { - long valid; - __pthreadLongUint_t reserved[13]; -} pthread_condattr_t ; - -typedef struct __pthread_transp_t { - __pthreadLongAddr_t reserved1; /* Reserved to posix_nt */ - __pthreadLongAddr_t reserved2; /* Reserved to posix_nt */ - unsigned short size; /* Size of data structure */ - unsigned char reserved3[2]; /* Reserved to posix_nt */ - __pthreadLongAddr_t reserved4; /* Reserved to posix_nt */ - __pthreadLongUint_t sequence; /* Thread sequence number */ - __pthreadLongUint_t reserved5[2]; /* Reserved to posix_nt */ - __pthreadLongAddr_t per_kt_area; /* Pointer to kernel context */ - __pthreadLongAddr_t stack_base; /* Current stack base */ - __pthreadLongAddr_t stack_reserve; /* Current stack reserve zone */ - __pthreadLongAddr_t stack_yellow; /* Current stack yellow zone */ - __pthreadLongAddr_t stack_guard; /* Current stack guard zone */ - __pthreadLongUint_t stack_size; /* Size of stack */ - __pthreadTsd_t tsd_values; /* TSD array (indexed by key) */ - unsigned long tsd_count; /* Number of TSD cells */ - __pthreadLongAddr_t reserved6; /* Reserved to posix_nt */ - __pthreadLongAddr_t reserved7; /* Reserved to posix_nt */ - unsigned int thread_flags; /* Dynamic external state */ -} pthread_transp_t, *pthread_transp_p; - -typedef pthread_transp_p pthread_t; - -typedef struct __pthread_attr_t { - long valid; - __pthreadLongString_t name; - __pthreadLongUint_t arg; - __pthreadLongUint_t reserved[19]; -} pthread_attr_t ; - -typedef unsigned int pthread_key_t; - -typedef struct sched_param { - int sched_priority; -} sched_param_t; - -/* Function Prototypes */ - -int pthread_create(pthread_t *thread, const pthread_attr_t *attr, - void *(*start_routine)(void*), void *arg); -int pthread_detach(pthread_t thread); -int pthread_join(pthread_t thread, void **value_ptr); -void pthread_exit(void *value_ptr); -int pthread_attr_init(pthread_attr_t *attr); -int pthread_attr_destroy(pthread_attr_t *attr); -int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize); -int pthread_attr_getstacksize(const pthread_attr_t *attr, - size_t *stacksize); -int pthread_cond_init(pthread_cond_t *cond, - const pthread_condattr_t *attr); -int pthread_cond_destroy(pthread_cond_t *cond); -int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); -int pthread_cond_timedwait(pthread_cond_t *cond, - pthread_mutex_t *mutex, - const struct timespec *abstime); -int pthread_cond_signal(pthread_cond_t *cond); -int pthread_cond_broadcast(pthread_cond_t *cond); -int pthread_key_create(pthread_key_t *key, void (*destructor)(void*)); -int pthread_key_delete(pthread_key_t key); -int pthread_mutex_destroy(pthread_mutex_t *mutex); -int pthread_mutex_init(pthread_mutex_t *mutex, - const pthread_mutexattr_t *attr); -int pthread_mutex_lock(pthread_mutex_t *mutex); -int pthread_mutex_trylock(pthread_mutex_t *mutex); -int pthread_mutex_unlock(pthread_mutex_t *mutex); -pthread_t pthread_self(); -int pthread_setspecific(pthread_key_t key, const void *value); -void *pthread_getspecific(pthread_key_t key); -int pthread_getschedparam(pthread_t thread, int *policy, - struct sched_param *param); -int pthread_setschedparam(pthread_t thread, int policy, - const struct sched_param *param); -int pthread_attr_setschedparam(pthread_attr_t *attr, - const struct sched_param *param); -int pthread_attr_getschedparam(const pthread_attr_t *attr, - struct sched_param *param); - -int pthread_delay_np(const struct timespec *interval); -int pthread_get_expiration_np(const struct timespec *delta, - struct timespec *abstime); - -# define SCHED_FIFO 1 -# define SCHED_RR 2 -# define SCHED_OTHER 3 - -int sched_yield(); -int sched_get_priority_max(int policy); -int sched_get_priority_min(int policy); - - -#ifdef __cplusplus -} -#endif - -#endif // PTHREAD_NT_H_INCLUDED diff --git a/omnithread/gnuradio/ot_solaris.h b/omnithread/gnuradio/ot_solaris.h deleted file mode 100644 index f4fea0b1..00000000 --- a/omnithread/gnuradio/ot_solaris.h +++ /dev/null @@ -1,47 +0,0 @@ -// Package : omnithread -// omnithread/solaris.h Created : 7/94 tjr -// -// Copyright (C) 1994,1995,1996, 1997 Olivetti & Oracle Research Laboratory -// -// This file is part of the omnithread library -// -// The omnithread library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library 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 -// Library General Public License for more details. -// -// You should have received a copy of the GNU Library General Public -// License along with this library; if not, write to the Free -// Software Foundation, Inc., 51 Franklin Street, Boston, MA -// 02110-1301, USA -// -// OMNI thread implementation classes for solaris threads. -// - -#ifndef __omnithread_solaris_h_ -#define __omnithread_solaris_h_ - -#include - -extern "C" void* omni_thread_wrapper(void* ptr); - -#define OMNI_MUTEX_IMPLEMENTATION \ - mutex_t sol_mutex; - -#define OMNI_CONDITION_IMPLEMENTATION \ - cond_t sol_cond; - -#define OMNI_SEMAPHORE_IMPLEMENTATION \ - sema_t sol_sem; - -#define OMNI_THREAD_IMPLEMENTATION \ - thread_t sol_thread; \ - static int sol_priority(priority_t); \ - friend void* omni_thread_wrapper(void* ptr); - -#endif diff --git a/omnithread/mach.cc b/omnithread/mach.cc deleted file mode 100644 index aa0465f4..00000000 --- a/omnithread/mach.cc +++ /dev/null @@ -1,714 +0,0 @@ -// Package : omnithread -// omnithread/mach.cc Created : 7/97 lars immisch lars@ibp.de -// -// Copyright (C) 1997 Immisch, Becker & Partner -// -// This file is part of the omnithread library -// -// The omnithread library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library 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 -// Library General Public License for more details. -// -// You should have received a copy of the GNU Library General Public -// License along with this library; if not, write to the Free -// Software Foundation, Inc., 51 Franklin Street, Boston, MA -// 02110-1301, USA -// - -// -// Implementation of OMNI thread abstraction for mach threads -// -// to the author's pleasure, mach cthreads are very similar to posix threads -// - -#include -#include -#include -#include -#include "gnuradio/omnithread.h" - -#define DB(x) // x -// #include or #include if DB is on. - -#define ERRNO(x) (x) - -// -// static variables -// - -int omni_thread::init_t::count = 0; - -omni_mutex* omni_thread::next_id_mutex; -int omni_thread::next_id = 0; - -static int normal_priority; -static int highest_priority; - -static size_t stack_size = 0; - -/////////////////////////////////////////////////////////////////////////// -// -// Mutex -// -/////////////////////////////////////////////////////////////////////////// - - -omni_mutex::omni_mutex(void) -{ - mutex_init(&mach_mutex); -} - - -omni_mutex::~omni_mutex(void) -{ - mutex_clear(&mach_mutex); -} - - -void omni_mutex::lock(void) -{ - mutex_lock(&mach_mutex); -} - - -void omni_mutex::unlock(void) -{ - mutex_unlock(&mach_mutex); -} - - - -/////////////////////////////////////////////////////////////////////////// -// -// Condition variable -// -/////////////////////////////////////////////////////////////////////////// - - -omni_condition::omni_condition(omni_mutex* m) : mutex(m) -{ - condition_init(&mach_cond); -} - - -omni_condition::~omni_condition(void) -{ - condition_clear(&mach_cond); -} - -void -omni_condition::wait(void) -{ - condition_wait(&mach_cond, &mutex->mach_mutex); -} - -typedef struct alarmclock_args { - unsigned long secs; - unsigned long nsecs; - bool wakeup; - condition_t condition; - mutex_t mutex; -}; - -any_t alarmclock(any_t arg) -{ - alarmclock_args* alarm = (alarmclock_args*)arg; - - omni_thread::sleep(alarm->secs, alarm->nsecs); - - mutex_lock(alarm->mutex); - - alarm->wakeup = TRUE; - - condition_signal(alarm->condition); - - mutex_unlock(alarm->mutex); - - return (any_t)TRUE; -} - -int omni_condition::timedwait(unsigned long abs_secs, unsigned long abs_nsecs) -{ - alarmclock_args alarm; - - omni_thread::get_time(&alarm.secs, &alarm.nsecs, 0, 0); - - if (abs_secs < alarm.secs || (abs_secs == alarm.secs && abs_nsecs <= alarm.nsecs)) - return ETIMEDOUT; - - alarm.secs = abs_secs - alarm.secs; - if (abs_nsecs <= alarm.nsecs) { - alarm.nsecs = 1000000 - alarm.nsecs + abs_nsecs; - alarm.secs--; - } - else { - alarm.nsecs = abs_nsecs - alarm.nsecs; - } - - alarm.mutex = &mutex->mach_mutex; - alarm.condition = &mach_cond; - alarm.wakeup = FALSE; - - cthread_t ct = cthread_fork((cthread_fn_t)alarmclock, (any_t)&alarm); - cthread_detach(ct); - - condition_wait(&mach_cond, &mutex->mach_mutex); - - if (alarm.wakeup) { - return 0; - } - - // interrupt the alarmclock thread sleep - cthread_abort(ct); - - // wait until it has signalled the condition - condition_wait(&mach_cond, &mutex->mach_mutex); - - return 1; -} - - -void omni_condition::signal(void) -{ - condition_signal(&mach_cond); -} - - -void omni_condition::broadcast(void) -{ - condition_signal(&mach_cond); -} - - - -/////////////////////////////////////////////////////////////////////////// -// -// Counting semaphore -// -/////////////////////////////////////////////////////////////////////////// - - -omni_semaphore::omni_semaphore(unsigned int initial) : c(&m) -{ - value = initial; -} - - -omni_semaphore::~omni_semaphore(void) -{ -} - - -void -omni_semaphore::wait(void) -{ - omni_mutex_lock l(m); - - while (value == 0) - c.wait(); - - value--; -} - - -int -omni_semaphore::trywait(void) -{ - omni_mutex_lock l(m); - - if (value == 0) - return 0; - - value--; - return 1; -} - - -void -omni_semaphore::post(void) -{ - omni_mutex_lock l(m); - - if (value == 0) - c.signal(); - - value++; -} - - - -/////////////////////////////////////////////////////////////////////////// -// -// Thread -// -/////////////////////////////////////////////////////////////////////////// - - - -// -// Initialisation function (gets called before any user code). -// - -omni_thread::init_t::init_t(void) -{ - if (count++ != 0) // only do it once however many objects get created. - return; - - // - // find base and max priority. - // This is the initial thread, so the max priority of this - // thread also applies to any newly created thread. - // - - kern_return_t error; - struct thread_sched_info info; - unsigned int info_count = THREAD_SCHED_INFO_COUNT; - - error = thread_info(thread_self(), THREAD_SCHED_INFO, (thread_info_t)&info, &info_count); - if (error != KERN_SUCCESS) { - DB(cerr << "omni_thread::init: error determining thread_info" << endl); - ::exit(1); - } - else { - normal_priority = info.base_priority; - highest_priority = info.max_priority; - } - - next_id_mutex = new omni_mutex; - - // - // Create object for this (i.e. initial) thread. - // - - omni_thread* t = new omni_thread; - - if (t->_state != STATE_NEW) { - DB(cerr << "omni_thread::init: problem creating initial thread object\n"); - ::exit(1); - } - - t->_state = STATE_RUNNING; - - t->mach_thread = cthread_self(); - - DB(cerr << "initial thread " << t->id() << endl); - - cthread_set_data(t->mach_thread, (any_t)t); -} - - -// -// Wrapper for thread creation. -// - -extern "C" void* -omni_thread_wrapper(void* ptr) -{ - omni_thread* me = (omni_thread*)ptr; - - DB(cerr << "omni_thread::wrapper: thread " << me->id() - << " started\n"); - - cthread_set_data(cthread_self(), (any_t)me); - - // - // Now invoke the thread function with the given argument. - // - - if (me->fn_void != NULL) { - (*me->fn_void)(me->thread_arg); - omni_thread::exit(); - } - - if (me->fn_ret != NULL) { - void* return_value = (*me->fn_ret)(me->thread_arg); - omni_thread::exit(return_value); - } - - if (me->detached) { - me->run(me->thread_arg); - omni_thread::exit(); - } else { - void* return_value = me->run_undetached(me->thread_arg); - omni_thread::exit(return_value); - } - - // should never get here. - - return NULL; -} - - -// -// Constructors for omni_thread - set up the thread object but don't -// start it running. -// - -// construct a detached thread running a given function. - -omni_thread::omni_thread(void (*fn)(void*), void* arg, priority_t pri) -{ - common_constructor(arg, pri, 1); - fn_void = fn; - fn_ret = NULL; -} - -// construct an undetached thread running a given function. - -omni_thread::omni_thread(void* (*fn)(void*), void* arg, priority_t pri) -{ - common_constructor(arg, pri, 0); - fn_void = NULL; - fn_ret = fn; -} - -// construct a thread which will run either run() or run_undetached(). - -omni_thread::omni_thread(void* arg, priority_t pri) -{ - common_constructor(arg, pri, 1); - fn_void = NULL; - fn_ret = NULL; -} - -// common part of all constructors. - -void omni_thread::common_constructor(void* arg, priority_t pri, int det) -{ - _state = STATE_NEW; - _priority = pri; - - next_id_mutex->lock(); - _id = next_id++; - next_id_mutex->unlock(); - - thread_arg = arg; - detached = det; // may be altered in start_undetached() - - _dummy = 0; - _values = 0; - _value_alloc = 0; - // posix_thread is set up in initialisation routine or start(). -} - - -// -// Destructor for omni_thread. -// - -omni_thread::~omni_thread(void) -{ - DB(cerr << "destructor called for thread " << id() << endl); - if (_values) { - for (key_t i=0; i < _value_alloc; i++) { - if (_values[i]) { - delete _values[i]; - } - } - delete [] _values; - } -} - - -// -// Start the thread -// - -void -omni_thread::start(void) -{ - omni_mutex_lock l(mutex); - - int rc; - - if (_state != STATE_NEW) - throw omni_thread_invalid(); - - mach_thread = cthread_fork(omni_thread_wrapper, (any_t)this); - - _state = STATE_RUNNING; - - if (detached) { - cthread_detach(mach_thread); - } -} - -// -// Start a thread which will run the member function run_undetached(). -// - -void -omni_thread::start_undetached(void) -{ - if ((fn_void != NULL) || (fn_ret != NULL)) - throw omni_thread_invalid(); - - detached = 0; - start(); -} - - -// -// join - simply check error conditions & call cthread_join. -// - -void -omni_thread::join(void** status) -{ - mutex.lock(); - - if ((_state != STATE_RUNNING) && (_state != STATE_TERMINATED)) { - mutex.unlock(); - throw omni_thread_invalid(); - } - - mutex.unlock(); - - if (this == self()) - throw omni_thread_invalid(); - - if (detached) - throw omni_thread_invalid(); - - DB(cerr << "omni_thread::join: doing cthread_join\n"); - - *status = cthread_join(mach_thread); - - delete this; -} - - -// -// Change this thread's priority. -// - -void -omni_thread::set_priority(priority_t pri) -{ - omni_mutex_lock l(mutex); - - if (_state != STATE_RUNNING) - throw omni_thread_invalid(); - - _priority = pri; - - kern_return_t rc = cthread_priority(mach_thread, mach_priority(pri), FALSE); - - if (rc != KERN_SUCCESS) - throw omni_thread_fatal(errno); -} - -// -// create - construct a new thread object and start it running. Returns thread -// object if successful, null pointer if not. -// - -// detached version - -omni_thread* -omni_thread::create(void (*fn)(void*), void* arg, priority_t pri) -{ - omni_thread* t = new omni_thread(fn, arg, pri); - - t->start(); - - return t; -} - -// undetached version - -omni_thread* -omni_thread::create(void* (*fn)(void*), void* arg, priority_t pri) -{ - omni_thread* t = new omni_thread(fn, arg, pri); - - t->start(); - - return t; -} - -// -// exit() _must_ lock the mutex even in the case of a detached thread. This is -// because a thread may run to completion before the thread that created it has -// had a chance to get out of start(). By locking the mutex we ensure that the -// creating thread must have reached the end of start() before we delete the -// thread object. Of course, once the call to start() returns, the user can -// still incorrectly refer to the thread object, but that's their problem. -// - -void omni_thread::exit(void* return_value) -{ - omni_thread* me = self(); - - if (me) - { - me->mutex.lock(); - - if (me->_state != STATE_RUNNING) - DB(cerr << "omni_thread::exit: thread not in \"running\" state\n"); - - me->_state = STATE_TERMINATED; - - me->mutex.unlock(); - - DB(cerr << "omni_thread::exit: thread " << me->id() << " detached " - << me->detached << " return value " << return_value << endl); - - if (me->detached) - delete me; - } - else - { - DB(cerr << "omni_thread::exit: called with a non-omnithread. Exit quietly." << endl); - } - cthread_exit(return_value); -} - -omni_thread* omni_thread::self(void) -{ - omni_thread* me; - - me = (omni_thread*)cthread_data(cthread_self()); - - if (!me) { - // This thread is not created by omni_thread::start because it - // doesn't has a class omni_thread instance attached to its key. - DB(cerr << "omni_thread::self: called with a non-ominthread. NULL is returned." << endl); - } - - return me; -} - -void omni_thread::yield(void) -{ - cthread_yield(); -} - -#define MAX_SLEEP_SECONDS (unsigned)4294966 // (2**32-2)/1000 - -void -omni_thread::sleep(unsigned long secs, unsigned long nanosecs) -{ - if (secs <= MAX_SLEEP_SECONDS) { - thread_switch(THREAD_NULL, SWITCH_OPTION_WAIT, secs * 1000 + nanosecs / 1000000); - return; - } - - unsigned no_of_max_sleeps = secs / MAX_SLEEP_SECONDS; - - for (unsigned i = 0; i < no_of_max_sleeps; i++) - thread_switch(THREAD_NULL, SWITCH_OPTION_WAIT, MAX_SLEEP_SECONDS * 1000); - - thread_switch(THREAD_NULL, SWITCH_OPTION_WAIT, - (secs % MAX_SLEEP_SECONDS) * 1000 + nanosecs / 1000000); - - return; -} - -void -omni_thread::get_time(unsigned long* abs_sec, unsigned long* abs_nsec, - unsigned long rel_sec, unsigned long rel_nsec) -{ - int rc; - unsigned long tv_sec; - unsigned long tv_nsec; - struct timeval tv; - - rc = gettimeofday(&tv, NULL); - if (rc) throw omni_thread_fatal(rc); - - tv_sec = tv.tv_sec; - tv_nsec = tv.tv_usec * 1000; - - tv_nsec += rel_nsec; - tv_sec += rel_sec + tv_nsec / 1000000000; - tv_nsec = tv_nsec % 1000000000; - - *abs_sec = tv_sec; - *abs_nsec = tv_nsec; -} - - -int -omni_thread::mach_priority(priority_t pri) -{ - switch (pri) { - - case PRIORITY_LOW: - return 0; - - case PRIORITY_NORMAL: - return normal_priority; - - case PRIORITY_HIGH: - return highest_priority; - - default: - return -1; - } -} - -void -omni_thread::stacksize(unsigned long sz) -{ - stack_size = sz; -} - -unsigned long -omni_thread::stacksize() -{ - return stack_size; -} - - -// -// Dummy thread -// - -#error This dummy thread code is not tested. It might work if you're lucky. - -class omni_thread_dummy : public omni_thread { -public: - inline omni_thread_dummy() : omni_thread() - { - _dummy = 1; - _state = STATE_RUNNING; - mach_thread = cthread_self(); - cthread_set_data(mach_thread, (any_t)this)); - } - inline ~omni_thread_dummy() - { - cthread_set_data(mach_thread, (any_t)0)); - } -}; - -omni_thread* -omni_thread::create_dummy() -{ - if (omni_thread::self()) - throw omni_thread_invalid(); - - return new omni_thread_dummy; -} - -void -omni_thread::release_dummy() -{ - omni_thread* self = omni_thread::self(); - if (!self || !self->_dummy) - throw omni_thread_invalid(); - - omni_thread_dummy* dummy = (omni_thread_dummy*)self; - delete dummy; -} - - -#define INSIDE_THREAD_IMPL_CC -#include "threaddata.cc" -#undef INSIDE_THREAD_IMPL_CC diff --git a/omnithread/nt.cc b/omnithread/nt.cc deleted file mode 100644 index 2c97d621..00000000 --- a/omnithread/nt.cc +++ /dev/null @@ -1,969 +0,0 @@ -// Package : omnithread -// omnithread/nt.cc Created : 6/95 tjr -// -// Copyright (C) 2006 Free Software Foundation, Inc. -// Copyright (C) 1995-1999 AT&T Laboratories Cambridge -// -// This file is part of the omnithread library -// -// The omnithread library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library 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 -// Library General Public License for more details. -// -// You should have received a copy of the GNU Library General Public -// License along with this library; if not, write to the Free -// Software Foundation, Inc., 51 Franklin Street, Boston, MA -// 02110-1301, USA -// - -// -// Implementation of OMNI thread abstraction for NT threads -// - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include - -#define DB(x) // x -//#include or #include if DB is on. - -static void get_time_now(unsigned long* abs_sec, unsigned long* abs_nsec); - -/////////////////////////////////////////////////////////////////////////// -// -// Mutex -// -/////////////////////////////////////////////////////////////////////////// - - -omni_mutex::omni_mutex(void) -{ - InitializeCriticalSection(&crit); -} - -omni_mutex::~omni_mutex(void) -{ - DeleteCriticalSection(&crit); -} - - - -/////////////////////////////////////////////////////////////////////////// -// -// Condition variable -// -/////////////////////////////////////////////////////////////////////////// - - -// -// Condition variables are tricky to implement using NT synchronisation -// primitives, since none of them have the atomic "release mutex and wait to be -// signalled" which is central to the idea of a condition variable. To get -// around this the solution is to record which threads are waiting and -// explicitly wake up those threads. -// -// Here we implement a condition variable using a list of waiting threads -// (protected by a critical section), and a per-thread semaphore (which -// actually only needs to be a binary semaphore). -// -// To wait on the cv, a thread puts itself on the list of waiting threads for -// that cv, then releases the mutex and waits on its own personal semaphore. A -// signalling thread simply takes a thread from the head of the list and kicks -// that thread's semaphore. Broadcast is simply implemented by kicking the -// semaphore of each waiting thread. -// -// The only other tricky part comes when a thread gets a timeout from a timed -// wait on its semaphore. Between returning with a timeout from the wait and -// entering the critical section, a signalling thread could get in, kick the -// waiting thread's semaphore and remove it from the list. If this happens, -// the waiting thread's semaphore is now out of step so it needs resetting, and -// the thread should indicate that it was signalled rather than that it timed -// out. -// -// It is possible that the thread calling wait or timedwait is not a -// omni_thread. In this case we have to provide a temporary data structure, -// i.e. for the duration of the call, for the thread to link itself on the -// list of waiting threads. _internal_omni_thread_dummy provides such -// a data structure and _internal_omni_thread_helper is a helper class to -// deal with this special case for wait() and timedwait(). Once created, -// the _internal_omni_thread_dummy is cached for use by the next wait() or -// timedwait() call from a non-omni_thread. This is probably worth doing -// because creating a Semaphore is quite heavy weight. - -class _internal_omni_thread_helper; - -class _internal_omni_thread_dummy : public omni_thread { -public: - inline _internal_omni_thread_dummy() : next(0) { } - inline ~_internal_omni_thread_dummy() { } - friend class _internal_omni_thread_helper; -private: - _internal_omni_thread_dummy* next; -}; - -class _internal_omni_thread_helper { -public: - inline _internal_omni_thread_helper() { - d = 0; - t = omni_thread::self(); - if (!t) { - omni_mutex_lock sync(cachelock); - if (cache) { - d = cache; - cache = cache->next; - } - else { - d = new _internal_omni_thread_dummy; - } - t = d; - } - } - inline ~_internal_omni_thread_helper() { - if (d) { - omni_mutex_lock sync(cachelock); - d->next = cache; - cache = d; - } - } - inline operator omni_thread* () { return t; } - inline omni_thread* operator->() { return t; } - - static _internal_omni_thread_dummy* cache; - static omni_mutex cachelock; - -private: - _internal_omni_thread_dummy* d; - omni_thread* t; -}; - -_internal_omni_thread_dummy* _internal_omni_thread_helper::cache = 0; -omni_mutex _internal_omni_thread_helper::cachelock; - - -omni_condition::omni_condition(omni_mutex* m) : mutex(m) -{ - InitializeCriticalSection(&crit); - waiting_head = waiting_tail = NULL; -} - - -omni_condition::~omni_condition(void) -{ - DeleteCriticalSection(&crit); - DB( if (waiting_head != NULL) { - cerr << "omni_condition::~omni_condition: list of waiting threads " - << "is not empty\n"; - } ) -} - - -void -omni_condition::wait(void) -{ - _internal_omni_thread_helper me; - - EnterCriticalSection(&crit); - - me->cond_next = NULL; - me->cond_prev = waiting_tail; - if (waiting_head == NULL) - waiting_head = me; - else - waiting_tail->cond_next = me; - waiting_tail = me; - me->cond_waiting = TRUE; - - LeaveCriticalSection(&crit); - - mutex->unlock(); - - DWORD result = WaitForSingleObject(me->cond_semaphore, INFINITE); - - mutex->lock(); - - if (result != WAIT_OBJECT_0) - throw omni_thread_fatal(GetLastError()); -} - - -int -omni_condition::timedwait(unsigned long abs_sec, unsigned long abs_nsec) -{ - _internal_omni_thread_helper me; - - EnterCriticalSection(&crit); - - me->cond_next = NULL; - me->cond_prev = waiting_tail; - if (waiting_head == NULL) - waiting_head = me; - else - waiting_tail->cond_next = me; - waiting_tail = me; - me->cond_waiting = TRUE; - - LeaveCriticalSection(&crit); - - mutex->unlock(); - - unsigned long now_sec, now_nsec; - - get_time_now(&now_sec, &now_nsec); - - DWORD timeout; - if ((abs_sec <= now_sec) && ((abs_sec < now_sec) || (abs_nsec < now_nsec))) - timeout = 0; - else { - timeout = (abs_sec-now_sec) * 1000; - - if( abs_nsec < now_nsec ) timeout -= (now_nsec-abs_nsec) / 1000000; - else timeout += (abs_nsec-now_nsec) / 1000000; - } - - DWORD result = WaitForSingleObject(me->cond_semaphore, timeout); - - if (result == WAIT_TIMEOUT) { - EnterCriticalSection(&crit); - - if (me->cond_waiting) { - if (me->cond_prev != NULL) - me->cond_prev->cond_next = me->cond_next; - else - waiting_head = me->cond_next; - if (me->cond_next != NULL) - me->cond_next->cond_prev = me->cond_prev; - else - waiting_tail = me->cond_prev; - me->cond_waiting = FALSE; - - LeaveCriticalSection(&crit); - - mutex->lock(); - return 0; - } - - // - // We timed out but another thread still signalled us. Wait for - // the semaphore (it _must_ have been signalled) to decrement it - // again. Return that we were signalled, not that we timed out. - // - - LeaveCriticalSection(&crit); - - result = WaitForSingleObject(me->cond_semaphore, INFINITE); - } - - if (result != WAIT_OBJECT_0) - throw omni_thread_fatal(GetLastError()); - - mutex->lock(); - return 1; -} - - -void -omni_condition::signal(void) -{ - EnterCriticalSection(&crit); - - if (waiting_head != NULL) { - omni_thread* t = waiting_head; - waiting_head = t->cond_next; - if (waiting_head == NULL) - waiting_tail = NULL; - else - waiting_head->cond_prev = NULL; - t->cond_waiting = FALSE; - - if (!ReleaseSemaphore(t->cond_semaphore, 1, NULL)) { - int rc = GetLastError(); - LeaveCriticalSection(&crit); - throw omni_thread_fatal(rc); - } - } - - LeaveCriticalSection(&crit); -} - - -void -omni_condition::broadcast(void) -{ - EnterCriticalSection(&crit); - - while (waiting_head != NULL) { - omni_thread* t = waiting_head; - waiting_head = t->cond_next; - if (waiting_head == NULL) - waiting_tail = NULL; - else - waiting_head->cond_prev = NULL; - t->cond_waiting = FALSE; - - if (!ReleaseSemaphore(t->cond_semaphore, 1, NULL)) { - int rc = GetLastError(); - LeaveCriticalSection(&crit); - throw omni_thread_fatal(rc); - } - } - - LeaveCriticalSection(&crit); -} - - - -/////////////////////////////////////////////////////////////////////////// -// -// Counting semaphore -// -/////////////////////////////////////////////////////////////////////////// - - -#define SEMAPHORE_MAX 0x7fffffff - - -omni_semaphore::omni_semaphore(unsigned int initial, unsigned int max_count) -{ - if (max_count > SEMAPHORE_MAX) - max_count= SEMAPHORE_MAX; - - nt_sem = CreateSemaphore(NULL, initial, max_count, NULL); - - if (nt_sem == NULL) { - DB( cerr << "omni_semaphore::omni_semaphore: CreateSemaphore error " - << GetLastError() << endl ); - throw omni_thread_fatal(GetLastError()); - } -} - - -omni_semaphore::~omni_semaphore(void) -{ - if (!CloseHandle(nt_sem)) { - DB( cerr << "omni_semaphore::~omni_semaphore: CloseHandle error " - << GetLastError() << endl ); - throw omni_thread_fatal(GetLastError()); - } -} - - -void -omni_semaphore::wait(void) -{ - if (WaitForSingleObject(nt_sem, INFINITE) != WAIT_OBJECT_0) - throw omni_thread_fatal(GetLastError()); -} - - -int -omni_semaphore::trywait(void) -{ - switch (WaitForSingleObject(nt_sem, 0)) { - - case WAIT_OBJECT_0: - return 1; - case WAIT_TIMEOUT: - return 0; - } - - throw omni_thread_fatal(GetLastError()); - return 0; /* keep msvc++ happy */ -} - - -void -omni_semaphore::post(void) -{ - if (!ReleaseSemaphore(nt_sem, 1, NULL) - && GetLastError() != ERROR_TOO_MANY_POSTS ) // MinGW fix--see ticket:95 in trac - throw omni_thread_fatal(GetLastError()); -} - - - -/////////////////////////////////////////////////////////////////////////// -// -// Thread -// -/////////////////////////////////////////////////////////////////////////// - - -// -// Static variables -// - -omni_mutex* omni_thread::next_id_mutex; -int omni_thread::next_id = 0; -static DWORD self_tls_index; - -static unsigned int stack_size = 0; - -// -// Initialisation function (gets called before any user code). -// - -static int& count() { - static int the_count = 0; - return the_count; -} - -omni_thread::init_t::init_t(void) -{ - if (count()++ != 0) // only do it once however many objects get created. - return; - - DB(cerr << "omni_thread::init: NT implementation initialising\n"); - - self_tls_index = TlsAlloc(); - - if (self_tls_index == 0xffffffff) - throw omni_thread_fatal(GetLastError()); - - next_id_mutex = new omni_mutex; - - // - // Create object for this (i.e. initial) thread. - // - - omni_thread* t = new omni_thread; - - t->_state = STATE_RUNNING; - - if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), - GetCurrentProcess(), &t->handle, - 0, FALSE, DUPLICATE_SAME_ACCESS)) - throw omni_thread_fatal(GetLastError()); - - t->nt_id = GetCurrentThreadId(); - - DB(cerr << "initial thread " << t->id() << " NT thread id " << t->nt_id - << endl); - - if (!TlsSetValue(self_tls_index, (LPVOID)t)) - throw omni_thread_fatal(GetLastError()); - - if (!SetThreadPriority(t->handle, nt_priority(PRIORITY_NORMAL))) - throw omni_thread_fatal(GetLastError()); -} - -omni_thread::init_t::~init_t(void) -{ - if (--count() != 0) return; - - omni_thread* self = omni_thread::self(); - if (!self) return; - - TlsSetValue(self_tls_index, (LPVOID)0); - delete self; - - delete next_id_mutex; - - TlsFree(self_tls_index); -} - -// -// Wrapper for thread creation. -// - -extern "C" -#ifndef __BCPLUSPLUS__ -unsigned __stdcall -#else -void _USERENTRY -#endif -omni_thread_wrapper(void* ptr) -{ - omni_thread* me = (omni_thread*)ptr; - - DB(cerr << "omni_thread_wrapper: thread " << me->id() - << " started\n"); - - if (!TlsSetValue(self_tls_index, (LPVOID)me)) - throw omni_thread_fatal(GetLastError()); - - // - // Now invoke the thread function with the given argument. - // - - if (me->fn_void != NULL) { - (*me->fn_void)(me->thread_arg); - omni_thread::exit(); - } - - if (me->fn_ret != NULL) { - void* return_value = (*me->fn_ret)(me->thread_arg); - omni_thread::exit(return_value); - } - - if (me->detached) { - me->run(me->thread_arg); - omni_thread::exit(); - } else { - void* return_value = me->run_undetached(me->thread_arg); - omni_thread::exit(return_value); - } - - // should never get here. -#ifndef __BCPLUSPLUS__ - return 0; -#endif -} - - -// -// Constructors for omni_thread - set up the thread object but don't -// start it running. -// - -// construct a detached thread running a given function. - -omni_thread::omni_thread(void (*fn)(void*), void* arg, priority_t pri) -{ - common_constructor(arg, pri, 1); - fn_void = fn; - fn_ret = NULL; -} - -// construct an undetached thread running a given function. - -omni_thread::omni_thread(void* (*fn)(void*), void* arg, priority_t pri) -{ - common_constructor(arg, pri, 0); - fn_void = NULL; - fn_ret = fn; -} - -// construct a thread which will run either run() or run_undetached(). - -omni_thread::omni_thread(void* arg, priority_t pri) -{ - common_constructor(arg, pri, 1); - fn_void = NULL; - fn_ret = NULL; -} - -// common part of all constructors. - -void -omni_thread::common_constructor(void* arg, priority_t pri, int det) -{ - _state = STATE_NEW; - _priority = pri; - - next_id_mutex->lock(); - _id = next_id++; - next_id_mutex->unlock(); - - thread_arg = arg; - detached = det; // may be altered in start_undetached() - - cond_semaphore = CreateSemaphore(NULL, 0, SEMAPHORE_MAX, NULL); - - if (cond_semaphore == NULL) - throw omni_thread_fatal(GetLastError()); - - cond_next = cond_prev = NULL; - cond_waiting = FALSE; - - handle = NULL; - - _dummy = 0; - _values = 0; - _value_alloc = 0; -} - - -// -// Destructor for omni_thread. -// - -omni_thread::~omni_thread(void) -{ - DB(cerr << "destructor called for thread " << id() << endl); - if (_values) { - for (key_t i=0; i < _value_alloc; i++) { - if (_values[i]) { - delete _values[i]; - } - } - delete [] _values; - } - if (handle && !CloseHandle(handle)) - throw omni_thread_fatal(GetLastError()); - if (cond_semaphore && !CloseHandle(cond_semaphore)) - throw omni_thread_fatal(GetLastError()); -} - - -// -// Start the thread -// - -void -omni_thread::start(void) -{ - omni_mutex_lock l(mutex); - - if (_state != STATE_NEW) - throw omni_thread_invalid(); - -#ifndef __BCPLUSPLUS__ - // MSVC++ or compatiable - unsigned int t; - handle = (HANDLE)_beginthreadex( - NULL, - stack_size, - omni_thread_wrapper, - (LPVOID)this, - CREATE_SUSPENDED, - &t); - nt_id = t; - if (handle == NULL) - throw omni_thread_fatal(GetLastError()); -#else - // Borland C++ - handle = (HANDLE)_beginthreadNT(omni_thread_wrapper, - stack_size, - (void*)this, - NULL, - CREATE_SUSPENDED, - &nt_id); - if (handle == INVALID_HANDLE_VALUE) - throw omni_thread_fatal(errno); -#endif - - if (!SetThreadPriority(handle, nt_priority(_priority))) - throw omni_thread_fatal(GetLastError()); - - if (ResumeThread(handle) == 0xffffffff) - throw omni_thread_fatal(GetLastError()); - - _state = STATE_RUNNING; -} - - -// -// Start a thread which will run the member function run_undetached(). -// - -void -omni_thread::start_undetached(void) -{ - if ((fn_void != NULL) || (fn_ret != NULL)) - throw omni_thread_invalid(); - - detached = 0; - start(); -} - - -// -// join - simply check error conditions & call WaitForSingleObject. -// - -void -omni_thread::join(void** status) -{ - mutex.lock(); - - if ((_state != STATE_RUNNING) && (_state != STATE_TERMINATED)) { - mutex.unlock(); - throw omni_thread_invalid(); - } - - mutex.unlock(); - - if (this == self()) - throw omni_thread_invalid(); - - if (detached) - throw omni_thread_invalid(); - - DB(cerr << "omni_thread::join: doing WaitForSingleObject\n"); - - if (WaitForSingleObject(handle, INFINITE) != WAIT_OBJECT_0) - throw omni_thread_fatal(GetLastError()); - - DB(cerr << "omni_thread::join: WaitForSingleObject succeeded\n"); - - if (status) - *status = return_val; - - delete this; -} - - -// -// Change this thread's priority. -// - -void -omni_thread::set_priority(priority_t pri) -{ - omni_mutex_lock l(mutex); - - if (_state != STATE_RUNNING) - throw omni_thread_invalid(); - - _priority = pri; - - if (!SetThreadPriority(handle, nt_priority(pri))) - throw omni_thread_fatal(GetLastError()); -} - - -// -// create - construct a new thread object and start it running. Returns thread -// object if successful, null pointer if not. -// - -// detached version - -omni_thread* -omni_thread::create(void (*fn)(void*), void* arg, priority_t pri) -{ - omni_thread* t = new omni_thread(fn, arg, pri); - t->start(); - return t; -} - -// undetached version - -omni_thread* -omni_thread::create(void* (*fn)(void*), void* arg, priority_t pri) -{ - omni_thread* t = new omni_thread(fn, arg, pri); - t->start(); - return t; -} - - -// -// exit() _must_ lock the mutex even in the case of a detached thread. This is -// because a thread may run to completion before the thread that created it has -// had a chance to get out of start(). By locking the mutex we ensure that the -// creating thread must have reached the end of start() before we delete the -// thread object. Of course, once the call to start() returns, the user can -// still incorrectly refer to the thread object, but that's their problem. -// - -void -omni_thread::exit(void* return_value) -{ - omni_thread* me = self(); - - if (me) - { - me->mutex.lock(); - - me->_state = STATE_TERMINATED; - - me->mutex.unlock(); - - DB(cerr << "omni_thread::exit: thread " << me->id() << " detached " - << me->detached << " return value " << return_value << endl); - - if (me->detached) { - delete me; - } else { - me->return_val = return_value; - } - } - else - { - DB(cerr << "omni_thread::exit: called with a non-omnithread. Exit quietly." << endl); - } -#ifndef __BCPLUSPLUS__ - // MSVC++ or compatiable - // _endthreadex() does not automatically closes the thread handle. - // The omni_thread dtor closes the thread handle. - _endthreadex(0); -#else - // Borland C++ - // _endthread() does not automatically closes the thread handle. - // _endthreadex() is only available if __MFC_COMPAT__ is defined and - // all it does is to call _endthread(). - _endthread(); -#endif -} - - -omni_thread* -omni_thread::self(void) -{ - LPVOID me; - - me = TlsGetValue(self_tls_index); - - if (me == NULL) { - DB(cerr << "omni_thread::self: called with a non-ominthread. NULL is returned." << endl); - } - return (omni_thread*)me; -} - - -void -omni_thread::yield(void) -{ - Sleep(0); -} - - -#define MAX_SLEEP_SECONDS (DWORD)4294966 // (2**32-2)/1000 - -void -omni_thread::sleep(unsigned long secs, unsigned long nanosecs) -{ - if (secs <= MAX_SLEEP_SECONDS) { - Sleep(secs * 1000 + nanosecs / 1000000); - return; - } - - DWORD no_of_max_sleeps = secs / MAX_SLEEP_SECONDS; - - for (DWORD i = 0; i < no_of_max_sleeps; i++) - Sleep(MAX_SLEEP_SECONDS * 1000); - - Sleep((secs % MAX_SLEEP_SECONDS) * 1000 + nanosecs / 1000000); -} - - -void -omni_thread::get_time(unsigned long* abs_sec, unsigned long* abs_nsec, - unsigned long rel_sec, unsigned long rel_nsec) -{ - get_time_now(abs_sec, abs_nsec); - *abs_nsec += rel_nsec; - *abs_sec += rel_sec + *abs_nsec / 1000000000; - *abs_nsec = *abs_nsec % 1000000000; -} - - -int -omni_thread::nt_priority(priority_t pri) -{ - switch (pri) { - - case PRIORITY_LOW: - return THREAD_PRIORITY_LOWEST; - - case PRIORITY_NORMAL: - return THREAD_PRIORITY_NORMAL; - - case PRIORITY_HIGH: - return THREAD_PRIORITY_HIGHEST; - } - - throw omni_thread_invalid(); - return 0; /* keep msvc++ happy */ -} - - -static void -get_time_now(unsigned long* abs_sec, unsigned long* abs_nsec) -{ - static int days_in_preceding_months[12] - = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; - static int days_in_preceding_months_leap[12] - = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }; - - SYSTEMTIME st; - - GetSystemTime(&st); - *abs_nsec = st.wMilliseconds * 1000000; - - // this formula should work until 1st March 2100 - - DWORD days = ((st.wYear - 1970) * 365 + (st.wYear - 1969) / 4 - + ((st.wYear % 4) - ? days_in_preceding_months[st.wMonth - 1] - : days_in_preceding_months_leap[st.wMonth - 1]) - + st.wDay - 1); - - *abs_sec = st.wSecond + 60 * (st.wMinute + 60 * (st.wHour + 24 * days)); -} - -void -omni_thread::stacksize(unsigned long sz) -{ - stack_size = sz; -} - -unsigned long -omni_thread::stacksize() -{ - return stack_size; -} - -// -// Dummy thread -// - -class omni_thread_dummy : public omni_thread { -public: - inline omni_thread_dummy() : omni_thread() - { - _dummy = 1; - _state = STATE_RUNNING; - - if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), - GetCurrentProcess(), &handle, - 0, FALSE, DUPLICATE_SAME_ACCESS)) - throw omni_thread_fatal(GetLastError()); - - nt_id = GetCurrentThreadId(); - - if (!TlsSetValue(self_tls_index, (LPVOID)this)) - throw omni_thread_fatal(GetLastError()); - } - inline ~omni_thread_dummy() - { - if (!TlsSetValue(self_tls_index, (LPVOID)0)) - throw omni_thread_fatal(GetLastError()); - } -}; - -omni_thread* -omni_thread::create_dummy() -{ - if (omni_thread::self()) - throw omni_thread_invalid(); - - return new omni_thread_dummy; -} - -void -omni_thread::release_dummy() -{ - omni_thread* self = omni_thread::self(); - if (!self || !self->_dummy) - throw omni_thread_invalid(); - - omni_thread_dummy* dummy = (omni_thread_dummy*)self; - delete dummy; -} - - -#if defined(__DMC__) && defined(_WINDLL) -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - return TRUE; -} -#endif - - -#define INSIDE_THREAD_IMPL_CC -#include "threaddata.cc" -#undef INSIDE_THREAD_IMPL_CC diff --git a/omnithread/omni_time.cc b/omnithread/omni_time.cc deleted file mode 100644 index 4920a683..00000000 --- a/omnithread/omni_time.cc +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007,2008 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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 3, or (at your option) - * any later version. - * - * GNU Radio 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif -#include -#include -#include -#include - - -omni_time::omni_time(double real_secs) -{ - double floor_secs = floor(real_secs); - d_secs = (long) floor_secs; - d_nsecs = (long) ((real_secs - floor_secs) * 1e9); // always positive -} - -omni_time -omni_time::time(const omni_time &delta_t) -{ - unsigned long abs_sec, abs_nsec; - unsigned long rel_sec = delta_t.d_secs; - unsigned long rel_nsec = delta_t.d_nsecs; - - omni_thread::get_time(&abs_sec, &abs_nsec, rel_sec, rel_nsec); - return omni_time(abs_sec, abs_nsec); -} - - -omni_time -operator+(const omni_time &x, const omni_time &y) -{ - omni_time r(x.d_secs + y.d_secs, x.d_nsecs + y.d_nsecs); - while (r.d_nsecs >= 1000000000){ - r.d_nsecs -= 1000000000; - r.d_secs++; - } - return r; -} - -omni_time -operator-(const omni_time &x, const omni_time &y) -{ - // assert(!(x < y)); - - omni_time r(x.d_secs - y.d_secs, x.d_nsecs - y.d_nsecs); - while (r.d_nsecs < 0){ - r.d_nsecs += 1000000000; - r.d_secs--; - } - return r; -} - -omni_time -operator+(const omni_time &x, double y) -{ - return x + omni_time(y); -} - -omni_time -operator-(const omni_time &x, double y) -{ - return x - omni_time(y); -} diff --git a/omnithread/posix.cc b/omnithread/posix.cc deleted file mode 100644 index 5574a8a0..00000000 --- a/omnithread/posix.cc +++ /dev/null @@ -1,982 +0,0 @@ -// Package : omnithread -// omnithread/posix.cc Created : 7/94 tjr -// -// Copyright (C) 2006 Free Software Foundation, Inc. -// Copyright (C) 1994-1999 AT&T Laboratories Cambridge -// -// This file is part of the omnithread library -// -// The omnithread library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library 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 -// Library General Public License for more details. -// -// You should have received a copy of the GNU Library General Public -// License along with this library; if not, write to the Free -// Software Foundation, Inc., 51 Franklin Street, Boston, MA -// 02110-1301, USA -// - -// -// Implementation of OMNI thread abstraction for posix threads -// -// The source below tests for the definition of the macros: -// PthreadDraftVersion -// PthreadSupportThreadPriority -// NoNanoSleep -// NeedPthreadInit -// -// As different draft versions of the pthread standard P1003.4a/P1003.1c -// define slightly different APIs, the macro 'PthreadDraftVersion' -// identifies the draft version supported by this particular platform. -// -// Some unix variants do not support thread priority unless a real-time -// kernel option is installed. The macro 'PthreadSupportThreadPriority', -// if defined, enables the use of thread priority. If it is not defined, -// setting or changing thread priority will be silently ignored. -// -// nanosleep() is defined in Posix P1003.4 since Draft 9 (?). -// Not all platforms support this standard. The macro 'NoNanoSleep' -// identifies platform that don't. -// - -#include -#include -#include -#include -#include - -#if (PthreadDraftVersion == 0) -#error "PthreadDraftVersion not defined. If not sure, define it to 10" -#endif - -#ifdef HAVE_NANOSLEEP -#undef NoNanoSleep -#else -#define NoNanoSleep -#endif - -#ifdef HAVE_SYS_TIME_H -// typedef of struct timeval and gettimeofday(); -#include -#include -#endif - -#if defined(__linux__) && defined(_MIT_POSIX_THREADS) -#include -#endif - -#if defined(__irix__) && defined(PthreadSupportThreadPriority) -#if _POSIX_THREAD_PRIORITY_SCHEDULING -#include -#endif -#endif - -#if 1 -#define DB(x) // x -#else -#define DB(x) x -#include -using std::cerr; -using std::endl; -#endif - -#if (PthreadDraftVersion <= 6) -#define ERRNO(x) (((x) != 0) ? (errno) : 0) -#ifdef __VMS -// pthread_setprio returns old priority on success (draft version 4: -// OpenVms version < 7) -#define THROW_ERRORS(x) { if ((x) == -1) throw omni_thread_fatal(errno); } -#else -#define THROW_ERRORS(x) { if ((x) != 0) throw omni_thread_fatal(errno); } -#endif -#else -#define ERRNO(x) (x) -#define THROW_ERRORS(x) { int rc = (x); \ - if (rc != 0) throw omni_thread_fatal(rc); } -#endif - - - -/////////////////////////////////////////////////////////////////////////// -// -// Mutex -// -/////////////////////////////////////////////////////////////////////////// - - -omni_mutex::omni_mutex(void) -{ -#if (PthreadDraftVersion == 4) - THROW_ERRORS(pthread_mutex_init(&posix_mutex, pthread_mutexattr_default)); -#else - THROW_ERRORS(pthread_mutex_init(&posix_mutex, 0)); -#endif -} - -omni_mutex::~omni_mutex(void) -{ - THROW_ERRORS(pthread_mutex_destroy(&posix_mutex)); -} - - -/////////////////////////////////////////////////////////////////////////// -// -// Condition variable -// -/////////////////////////////////////////////////////////////////////////// - - -omni_condition::omni_condition(omni_mutex* m) : mutex(m) -{ -#if (PthreadDraftVersion == 4) - THROW_ERRORS(pthread_cond_init(&posix_cond, pthread_condattr_default)); -#else - THROW_ERRORS(pthread_cond_init(&posix_cond, 0)); -#endif -} - -omni_condition::~omni_condition(void) -{ - THROW_ERRORS(pthread_cond_destroy(&posix_cond)); -} - -void -omni_condition::wait(void) -{ - THROW_ERRORS(pthread_cond_wait(&posix_cond, &mutex->posix_mutex)); -} - -int -omni_condition::timedwait(unsigned long secs, unsigned long nanosecs) -{ - timespec rqts = { secs, nanosecs }; - -again: - int rc = ERRNO(pthread_cond_timedwait(&posix_cond, - &mutex->posix_mutex, &rqts)); - if (rc == 0) - return 1; - -#if (PthreadDraftVersion <= 6) - if (rc == EAGAIN) - return 0; -#endif - - // Some versions of unix produces this errno when the wait was - // interrupted by a unix signal or fork. - // Some versions of the glibc 2.0.x produces this errno when the - // program is debugged under gdb. Straightly speaking this is non-posix - // compliant. We catch this here to make debugging possible. - if (rc == EINTR) - goto again; - - if (rc == ETIMEDOUT) - return 0; - - throw omni_thread_fatal(rc); -#ifdef _MSC_VER - return 0; -#endif -} - -void -omni_condition::signal(void) -{ - THROW_ERRORS(pthread_cond_signal(&posix_cond)); -} - -void -omni_condition::broadcast(void) -{ - THROW_ERRORS(pthread_cond_broadcast(&posix_cond)); -} - - - -/////////////////////////////////////////////////////////////////////////// -// -// Counting (or binary) semaphore -// -/////////////////////////////////////////////////////////////////////////// - - -omni_semaphore::omni_semaphore(unsigned int initial, unsigned int _max_count) : c(&m) -{ - value = initial; - max_count = _max_count; - if (value < 0 || max_count < 1) - throw omni_thread_fatal(0); -} - -omni_semaphore::~omni_semaphore(void) -{ -} - -void -omni_semaphore::wait(void) -{ - omni_mutex_lock l(m); - - while (value == 0) - c.wait(); - - value--; -} - -int -omni_semaphore::trywait(void) -{ - omni_mutex_lock l(m); - - if (value == 0) - return 0; - - value--; - return 1; -} - -void -omni_semaphore::post(void) -{ - { - omni_mutex_lock l(m); - if (value < max_count) - value++; - } - - c.signal(); -} - - - -/////////////////////////////////////////////////////////////////////////// -// -// Thread -// -/////////////////////////////////////////////////////////////////////////// - - -// -// static variables -// - -omni_mutex* omni_thread::next_id_mutex; -int omni_thread::next_id = 0; - -static pthread_key_t self_key; - -#ifdef PthreadSupportThreadPriority -static int lowest_priority; -static int normal_priority; -static int highest_priority; -#endif - -#if defined(__osf1__) && defined(__alpha__) || defined(__VMS) -// omniORB requires a larger stack size than the default (21120) on OSF/1 -static size_t stack_size = 32768; -#elif defined(__rtems__) -static size_t stack_size = ThreadStackSize; -#elif defined(__aix__) -static size_t stack_size = 262144; -#else -static size_t stack_size = 0; -#endif - -// -// Initialisation function (gets called before any user code). -// - -static int& count() { - static int the_count = 0; - return the_count; -} - -omni_thread::init_t::init_t(void) -{ - if (count()++ != 0) // only do it once however many objects get created. - return; - - DB(cerr << "omni_thread::init: posix 1003.4a/1003.1c (draft " - << PthreadDraftVersion << ") implementation initialising\n"); - -#ifdef NeedPthreadInit - - pthread_init(); - -#endif - -#if (PthreadDraftVersion == 4) - THROW_ERRORS(pthread_keycreate(&self_key, NULL)); -#else - THROW_ERRORS(pthread_key_create(&self_key, NULL)); -#endif - -#ifdef PthreadSupportThreadPriority - -#if defined(__osf1__) && defined(__alpha__) || defined(__VMS) - - lowest_priority = PRI_OTHER_MIN; - highest_priority = PRI_OTHER_MAX; - -#elif defined(__hpux__) - - lowest_priority = PRI_OTHER_MIN; - highest_priority = PRI_OTHER_MAX; - -#elif defined(__sunos__) && (__OSVERSION__ == 5) - - // a bug in pthread_attr_setschedparam means lowest priority is 1 not 0 - - lowest_priority = 1; - highest_priority = 3; - -#else - - lowest_priority = sched_get_priority_min(SCHED_FIFO); - highest_priority = sched_get_priority_max(SCHED_FIFO); - -#endif - - switch (highest_priority - lowest_priority) { - - case 0: - case 1: - normal_priority = lowest_priority; - break; - - default: - normal_priority = lowest_priority + 1; - break; - } - -#endif /* PthreadSupportThreadPriority */ - - next_id_mutex = new omni_mutex; - - // - // Create object for this (i.e. initial) thread. - // - - omni_thread* t = new omni_thread; - - t->_state = STATE_RUNNING; - - t->posix_thread = pthread_self (); - - DB(cerr << "initial thread " << t->id() << endl); - - THROW_ERRORS(pthread_setspecific(self_key, (void*)t)); - -#ifdef PthreadSupportThreadPriority - -#if (PthreadDraftVersion == 4) - - THROW_ERRORS(pthread_setprio(t->posix_thread, - posix_priority(PRIORITY_NORMAL))); - -#elif (PthreadDraftVersion == 6) - - pthread_attr_t attr; - pthread_attr_init(&attr); - - THROW_ERRORS(pthread_attr_setprio(&attr, posix_priority(PRIORITY_NORMAL))); - - THROW_ERRORS(pthread_setschedattr(t->posix_thread, attr)); - -#else - - struct sched_param sparam; - - sparam.sched_priority = posix_priority(PRIORITY_NORMAL); - - THROW_ERRORS(pthread_setschedparam(t->posix_thread, SCHED_OTHER, &sparam)); - -#endif /* PthreadDraftVersion */ - -#endif /* PthreadSupportThreadPriority */ -} - -omni_thread::init_t::~init_t(void) -{ - if (--count() != 0) return; - - omni_thread* self = omni_thread::self(); - if (!self) return; - - pthread_setspecific(self_key, 0); - delete self; - - delete next_id_mutex; -} - -// -// Wrapper for thread creation. -// - -extern "C" void* -omni_thread_wrapper(void* ptr) -{ - omni_thread* me = (omni_thread*)ptr; - - DB(cerr << "omni_thread_wrapper: thread " << me->id() - << " started\n"); - - THROW_ERRORS(pthread_setspecific(self_key, me)); - - // - // Now invoke the thread function with the given argument. - // - - if (me->fn_void != NULL) { - (*me->fn_void)(me->thread_arg); - omni_thread::exit(); - } - - if (me->fn_ret != NULL) { - void* return_value = (*me->fn_ret)(me->thread_arg); - omni_thread::exit(return_value); - } - - if (me->detached) { - me->run(me->thread_arg); - omni_thread::exit(); - } else { - void* return_value = me->run_undetached(me->thread_arg); - omni_thread::exit(return_value); - } - - // should never get here. - - return NULL; -} - - -// -// Constructors for omni_thread - set up the thread object but don't -// start it running. -// - -// construct a detached thread running a given function. - -omni_thread::omni_thread(void (*fn)(void*), void* arg, priority_t pri) -{ - common_constructor(arg, pri, 1); - fn_void = fn; - fn_ret = NULL; -} - -// construct an undetached thread running a given function. - -omni_thread::omni_thread(void* (*fn)(void*), void* arg, priority_t pri) -{ - common_constructor(arg, pri, 0); - fn_void = NULL; - fn_ret = fn; -} - -// construct a thread which will run either run() or run_undetached(). - -omni_thread::omni_thread(void* arg, priority_t pri) -{ - common_constructor(arg, pri, 1); - fn_void = NULL; - fn_ret = NULL; -} - -// common part of all constructors. - -void -omni_thread::common_constructor(void* arg, priority_t pri, int det) -{ - _state = STATE_NEW; - _priority = pri; - - next_id_mutex->lock(); - _id = next_id++; - next_id_mutex->unlock(); - - thread_arg = arg; - detached = det; // may be altered in start_undetached() - - _dummy = 0; - _values = 0; - _value_alloc = 0; - // posix_thread is set up in initialisation routine or start(). -} - - -// -// Destructor for omni_thread. -// - -omni_thread::~omni_thread(void) -{ - DB(cerr << "destructor called for thread " << id() << endl); - if (_values) { - for (key_t i=0; i < _value_alloc; i++) { - if (_values[i]) { - delete _values[i]; - } - } - delete [] _values; - } -} - - -// -// Start the thread -// - -void -omni_thread::start(void) -{ - omni_mutex_lock l(mutex); - - if (_state != STATE_NEW) - throw omni_thread_invalid(); - - pthread_attr_t attr; - -#if (PthreadDraftVersion == 4) - pthread_attr_create(&attr); -#else - pthread_attr_init(&attr); -#endif - -#if (PthreadDraftVersion == 8) - pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); -#endif - -#ifdef PthreadSupportThreadPriority - -#if (PthreadDraftVersion <= 6) - - THROW_ERRORS(pthread_attr_setprio(&attr, posix_priority(_priority))); - -#else - - struct sched_param sparam; - - sparam.sched_priority = posix_priority(_priority); - - THROW_ERRORS(pthread_attr_setschedparam(&attr, &sparam)); - -#endif /* PthreadDraftVersion */ - -#endif /* PthreadSupportThreadPriority */ - -#if !defined(__linux__) - if (stack_size) { - THROW_ERRORS(pthread_attr_setstacksize(&attr, stack_size)); - } -#endif - - -#if (PthreadDraftVersion == 4) - THROW_ERRORS(pthread_create(&posix_thread, attr, omni_thread_wrapper, - (void*)this)); - pthread_attr_delete(&attr); -#else - THROW_ERRORS(pthread_create(&posix_thread, &attr, omni_thread_wrapper, - (void*)this)); - pthread_attr_destroy(&attr); -#endif - - _state = STATE_RUNNING; - - if (detached) { - -#if (PthreadDraftVersion <= 6) - THROW_ERRORS(pthread_detach(&posix_thread)); -#else - THROW_ERRORS(pthread_detach(posix_thread)); -#endif - } -} - - -// -// Start a thread which will run the member function run_undetached(). -// - -void -omni_thread::start_undetached(void) -{ - if ((fn_void != NULL) || (fn_ret != NULL)) - throw omni_thread_invalid(); - - detached = 0; - start(); -} - - -// -// join - simply check error conditions & call pthread_join. -// - -void -omni_thread::join(void** status) -{ - mutex.lock(); - - if ((_state != STATE_RUNNING) && (_state != STATE_TERMINATED)) { - mutex.unlock(); - throw omni_thread_invalid(); - } - - mutex.unlock(); - - if (this == self()) - throw omni_thread_invalid(); - - if (detached) - throw omni_thread_invalid(); - - DB(cerr << "omni_thread::join: doing pthread_join\n"); - - THROW_ERRORS(pthread_join(posix_thread, status)); - - DB(cerr << "omni_thread::join: pthread_join succeeded\n"); - -#if (PthreadDraftVersion == 4) - // With draft 4 pthreads implementations (HPUX 10.x and - // Digital Unix 3.2), have to detach the thread after - // join. If not, the storage for the thread will not be - // be reclaimed. - THROW_ERRORS(pthread_detach(&posix_thread)); -#endif - - delete this; -} - - -// -// Change this thread's priority. -// - -void -omni_thread::set_priority(priority_t pri) -{ - omni_mutex_lock l(mutex); - - if (_state != STATE_RUNNING) - throw omni_thread_invalid(); - - _priority = pri; - -#ifdef PthreadSupportThreadPriority - -#if (PthreadDraftVersion == 4) - - THROW_ERRORS(pthread_setprio(posix_thread, posix_priority(pri))); - -#elif (PthreadDraftVersion == 6) - - pthread_attr_t attr; - pthread_attr_init(&attr); - - THROW_ERRORS(pthread_attr_setprio(&attr, posix_priority(pri))); - - THROW_ERRORS(pthread_setschedattr(posix_thread, attr)); - -#else - - struct sched_param sparam; - - sparam.sched_priority = posix_priority(pri); - - THROW_ERRORS(pthread_setschedparam(posix_thread, SCHED_OTHER, &sparam)); - -#endif /* PthreadDraftVersion */ - -#endif /* PthreadSupportThreadPriority */ -} - - -// -// create - construct a new thread object and start it running. Returns thread -// object if successful, null pointer if not. -// - -// detached version - -omni_thread* -omni_thread::create(void (*fn)(void*), void* arg, priority_t pri) -{ - omni_thread* t = new omni_thread(fn, arg, pri); - - t->start(); - - return t; -} - -// undetached version - -omni_thread* -omni_thread::create(void* (*fn)(void*), void* arg, priority_t pri) -{ - omni_thread* t = new omni_thread(fn, arg, pri); - - t->start(); - - return t; -} - - -// -// exit() _must_ lock the mutex even in the case of a detached thread. This is -// because a thread may run to completion before the thread that created it has -// had a chance to get out of start(). By locking the mutex we ensure that the -// creating thread must have reached the end of start() before we delete the -// thread object. Of course, once the call to start() returns, the user can -// still incorrectly refer to the thread object, but that's their problem. -// - -void -omni_thread::exit(void* return_value) -{ - omni_thread* me = self(); - - if (me) - { - me->mutex.lock(); - - me->_state = STATE_TERMINATED; - - me->mutex.unlock(); - - DB(cerr << "omni_thread::exit: thread " << me->id() << " detached " - << me->detached << " return value " << return_value << endl); - - if (me->detached) - delete me; - } - else - { - DB(cerr << "omni_thread::exit: called with a non-omnithread. Exit quietly." << endl); - } - - pthread_exit(return_value); -} - - -omni_thread* -omni_thread::self(void) -{ - omni_thread* me; - -#if (PthreadDraftVersion <= 6) - - THROW_ERRORS(pthread_getspecific(self_key, (void**)&me)); - -#else - - me = (omni_thread *)pthread_getspecific(self_key); - -#endif - - if (!me) { - // This thread is not created by omni_thread::start because it - // doesn't has a class omni_thread instance attached to its key. - DB(cerr << "omni_thread::self: called with a non-omnithread. NULL is returned." << endl); - } - - return me; -} - - -void -omni_thread::yield(void) -{ -#if (PthreadDraftVersion == 6) - - pthread_yield(NULL); - -#elif (PthreadDraftVersion < 9) - - pthread_yield(); - -#else - - THROW_ERRORS(sched_yield()); - -#endif -} - - -void -omni_thread::sleep(unsigned long secs, unsigned long nanosecs) -{ - timespec rqts = { secs, nanosecs }; - -#ifndef NoNanoSleep - - timespec remain; - while (nanosleep(&rqts, &remain)) { - if (errno == EINTR) { - rqts.tv_sec = remain.tv_sec; - rqts.tv_nsec = remain.tv_nsec; - continue; - } - else - throw omni_thread_fatal(errno); - } -#else - -#if defined(__osf1__) && defined(__alpha__) || defined(__hpux__) && (__OSVERSION__ == 10) || defined(__VMS) || defined(__SINIX__) || defined (__POSIX_NT__) - - if (pthread_delay_np(&rqts) != 0) - throw omni_thread_fatal(errno); - -#elif defined(__linux__) || defined(__aix__) - - if (secs > 2000) { - while ((secs = ::sleep(secs))) ; - } else { - usleep(secs * 1000000 + (nanosecs / 1000)); - } - -#elif defined(__darwin__) || defined(__macos__) - - // Single UNIX Specification says argument of usleep() must be - // less than 1,000,000. - secs += nanosecs / 1000000000; - nanosecs %= 1000000000; - while ((secs = ::sleep(secs))) ; - usleep(nanosecs / 1000); - -#else - - throw omni_thread_invalid(); - -#endif -#endif /* NoNanoSleep */ -} - - -void -omni_thread::get_time(unsigned long* abs_sec, unsigned long* abs_nsec, - unsigned long rel_sec, unsigned long rel_nsec) -{ - timespec abs; - -#if defined(__osf1__) && defined(__alpha__) || defined(__hpux__) && (__OSVERSION__ == 10) || defined(__VMS) || defined(__SINIX__) || defined(__POSIX_NT__) - - timespec rel; - rel.tv_sec = rel_sec; - rel.tv_nsec = rel_nsec; - THROW_ERRORS(pthread_get_expiration_np(&rel, &abs)); - -#else - -#ifdef HAVE_CLOCK_GETTIME /* __linux__ || __aix__ */ - - clock_gettime(CLOCK_REALTIME, &abs); - -#elif defined(HAVE_GETTIMEOFDAY) /* defined(__linux__) || defined(__aix__) || defined(__SCO_VERSION__) || defined(__darwin__) || defined(__macos__) */ - - struct timeval tv; - gettimeofday(&tv, NULL); - abs.tv_sec = tv.tv_sec; - abs.tv_nsec = tv.tv_usec * 1000; - -#else -#error no get time support -#endif /* __linux__ || __aix__ */ - - abs.tv_nsec += rel_nsec; - abs.tv_sec += rel_sec + abs.tv_nsec / 1000000000; - abs.tv_nsec = abs.tv_nsec % 1000000000; - -#endif /* __osf1__ && __alpha__ */ - - *abs_sec = abs.tv_sec; - *abs_nsec = abs.tv_nsec; -} - - -int -omni_thread::posix_priority(priority_t pri) -{ -#ifdef PthreadSupportThreadPriority - switch (pri) { - - case PRIORITY_LOW: - return lowest_priority; - - case PRIORITY_NORMAL: - return normal_priority; - - case PRIORITY_HIGH: - return highest_priority; - - } -#endif - - throw omni_thread_invalid(); -#ifdef _MSC_VER - return 0; -#endif -} - -void -omni_thread::stacksize(unsigned long sz) -{ - stack_size = sz; -} - -unsigned long -omni_thread::stacksize() -{ - return stack_size; -} - -// -// Dummy thread -// - -class omni_thread_dummy : public omni_thread { -public: - inline omni_thread_dummy() : omni_thread() - { - _dummy = 1; - _state = STATE_RUNNING; - posix_thread = pthread_self(); - THROW_ERRORS(pthread_setspecific(self_key, (void*)this)); - } - inline ~omni_thread_dummy() - { - THROW_ERRORS(pthread_setspecific(self_key, 0)); - } -}; - -omni_thread* -omni_thread::create_dummy() -{ - if (omni_thread::self()) - throw omni_thread_invalid(); - - return new omni_thread_dummy; -} - -void -omni_thread::release_dummy() -{ - omni_thread* self = omni_thread::self(); - if (!self || !self->_dummy) - throw omni_thread_invalid(); - - omni_thread_dummy* dummy = (omni_thread_dummy*)self; - delete dummy; -} - - -#define INSIDE_THREAD_IMPL_CC -#include "threaddata.cc" -#undef INSIDE_THREAD_IMPL_CC diff --git a/omnithread/solaris.cc b/omnithread/solaris.cc deleted file mode 100644 index eedaaa99..00000000 --- a/omnithread/solaris.cc +++ /dev/null @@ -1,615 +0,0 @@ -// Package : omnithread -// omnithread/solaris.cc Created : 7/94 tjr -// -// Copyright (C) 1994-1999 AT&T Laboratories Cambridge -// -// This file is part of the omnithread library -// -// The omnithread library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library 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 -// Library General Public License for more details. -// -// You should have received a copy of the GNU Library General Public -// License along with this library; if not, write to the Free -// Software Foundation, Inc., 51 Franklin Street, Boston, MA -// 02110-1301, USA -// -// -// Implementation of OMNI thread abstraction for solaris threads. -// - -#include -#include -#include - -#define DB(x) // x -// #include or #include if DB is on. - -#define THROW_ERRORS(x) { int rc = (x); \ - if (rc != 0) throw omni_thread_fatal(rc); } - - - -/////////////////////////////////////////////////////////////////////////// -// -// Mutex -// -/////////////////////////////////////////////////////////////////////////// - - -omni_mutex::omni_mutex(void) -{ - THROW_ERRORS(mutex_init(&sol_mutex, USYNC_THREAD, 0)); -} - -omni_mutex::~omni_mutex(void) -{ - THROW_ERRORS(mutex_destroy(&sol_mutex)); -} - -void -omni_mutex::lock(void) -{ - THROW_ERRORS(mutex_lock(&sol_mutex)); -} - -void -omni_mutex::unlock(void) -{ - THROW_ERRORS(mutex_unlock(&sol_mutex)); -} - - - -/////////////////////////////////////////////////////////////////////////// -// -// Condition variable -// -/////////////////////////////////////////////////////////////////////////// - - -omni_condition::omni_condition(omni_mutex* m) : mutex(m) -{ - THROW_ERRORS(cond_init(&sol_cond, USYNC_THREAD, 0)); -} - -omni_condition::~omni_condition(void) -{ - THROW_ERRORS(cond_destroy(&sol_cond)); -} - -void -omni_condition::wait(void) -{ - THROW_ERRORS(cond_wait(&sol_cond, &mutex->sol_mutex)); -} - -int -omni_condition::timedwait(unsigned long secs, unsigned long nanosecs) -{ - timespec rqts = { secs, nanosecs }; - - again: - int rc = cond_timedwait(&sol_cond, &mutex->sol_mutex, &rqts); - - if (rc == 0) - return 1; - - if (rc == EINTR) - goto again; - - if (rc == ETIME) - return 0; - - throw omni_thread_fatal(rc); -} - -void -omni_condition::signal(void) -{ - THROW_ERRORS(cond_signal(&sol_cond)); -} - -void -omni_condition::broadcast(void) -{ - THROW_ERRORS(cond_broadcast(&sol_cond)); -} - - - -/////////////////////////////////////////////////////////////////////////// -// -// Counting semaphore -// -/////////////////////////////////////////////////////////////////////////// - - -omni_semaphore::omni_semaphore(unsigned int initial) -{ - THROW_ERRORS(sema_init(&sol_sem, initial, USYNC_THREAD, NULL)); -} - -omni_semaphore::~omni_semaphore(void) -{ - THROW_ERRORS(sema_destroy(&sol_sem)); -} - -void -omni_semaphore::wait(void) -{ - THROW_ERRORS(sema_wait(&sol_sem)); -} - -void -omni_semaphore::post(void) -{ - THROW_ERRORS(sema_post(&sol_sem)); -} - - - -/////////////////////////////////////////////////////////////////////////// -// -// Thread -// -/////////////////////////////////////////////////////////////////////////// - - -// -// Static variables -// - -int omni_thread::init_t::count = 0; - -omni_mutex* omni_thread::next_id_mutex; -int omni_thread::next_id = 0; - -static thread_key_t self_key; - -static size_t stack_size = 0; - -// -// Initialisation function (gets called before any user code). -// - -omni_thread::init_t::init_t(void) -{ - if (count++ != 0) // only do it once however many objects get created. - return; - - DB(cerr << "omni_thread::init: solaris implementation initialising\n"); - - THROW_ERRORS(thr_keycreate(&self_key, NULL)); - - next_id_mutex = new omni_mutex; - - // - // Create object for this (i.e. initial) thread. - // - - omni_thread* t = new omni_thread; - - t->_state = STATE_RUNNING; - - t->sol_thread = thr_self(); - - DB(cerr << "initial thread " << t->id() << " sol_thread " << t->sol_thread - << endl); - - THROW_ERRORS(thr_setspecific(self_key, (void*)t)); - - THROW_ERRORS(thr_setprio(t->sol_thread, sol_priority(PRIORITY_NORMAL))); -} - - -// -// Wrapper for thread creation. -// - -extern "C" void* -omni_thread_wrapper(void* ptr) -{ - omni_thread* me = (omni_thread*)ptr; - - DB(cerr << "omni_thread::wrapper: thread " << me->id() - << " started\n"); - - THROW_ERRORS(thr_setspecific(self_key, me)); - - // - // Now invoke the thread function with the given argument. - // - - if (me->fn_void != NULL) { - (*me->fn_void)(me->thread_arg); - omni_thread::exit(); - } - - if (me->fn_ret != NULL) { - void* return_value = (*me->fn_ret)(me->thread_arg); - omni_thread::exit(return_value); - } - - if (me->detached) { - me->run(me->thread_arg); - omni_thread::exit(); - } else { - void* return_value = me->run_undetached(me->thread_arg); - omni_thread::exit(return_value); - } - - // should never get here. - - return NULL; -} - - -// -// Constructors for omni_thread - set up the thread object but don't -// start it running. -// - -// construct a detached thread running a given function. - -omni_thread::omni_thread(void (*fn)(void*), void* arg, priority_t pri) -{ - common_constructor(arg, pri, 1); - fn_void = fn; - fn_ret = NULL; -} - -// construct an undetached thread running a given function. - -omni_thread::omni_thread(void* (*fn)(void*), void* arg, priority_t pri) -{ - common_constructor(arg, pri, 0); - fn_void = NULL; - fn_ret = fn; -} - -// construct a thread which will run either run() or run_undetached(). - -omni_thread::omni_thread(void* arg, priority_t pri) -{ - common_constructor(arg, pri, 1); - fn_void = NULL; - fn_ret = NULL; -} - -// common part of all constructors. - -void -omni_thread::common_constructor(void* arg, priority_t pri, int det) -{ - _state = STATE_NEW; - _priority = pri; - - next_id_mutex->lock(); - _id = next_id++; - next_id_mutex->unlock(); - - thread_arg = arg; - detached = det; // may be altered in start_undetached() - - _dummy = 0; - _values = 0; - _value_alloc = 0; - // sol_thread is set up in initialisation routine or start(). -} - - -// -// Destructor for omni_thread. -// - -omni_thread::~omni_thread(void) -{ - DB(cerr << "destructor called for thread " << id() << endl); - if (_values) { - for (key_t i=0; i < _value_alloc; i++) { - if (_values[i]) { - delete _values[i]; - } - } - delete [] _values; - } -} - - -// -// Start the thread -// - -void -omni_thread::start(void) -{ - long flags = 0; - - if (detached) - flags |= THR_DETACHED; - - omni_mutex_lock l(mutex); - - if (_state != STATE_NEW) - throw omni_thread_invalid(); - - THROW_ERRORS(thr_create(0, stack_size, omni_thread_wrapper, (void*)this, flags, - &sol_thread)); - - _state = STATE_RUNNING; - - THROW_ERRORS(thr_setprio(sol_thread, sol_priority(_priority))); -} - - -// -// Start a thread which will run the member function run_undetached(). -// - -void -omni_thread::start_undetached(void) -{ - if ((fn_void != NULL) || (fn_ret != NULL)) - throw omni_thread_invalid(); - - detached = 0; - start(); -} - - -// -// join - simply check error conditions & call thr_join. -// - -void -omni_thread::join(void** status) -{ - mutex.lock(); - - if ((_state != STATE_RUNNING) && (_state != STATE_TERMINATED)) { - mutex.unlock(); - throw omni_thread_invalid(); - } - - mutex.unlock(); - - if (this == self()) - throw omni_thread_invalid(); - - if (detached) - throw omni_thread_invalid(); - - DB(cerr << "omni_thread::join: doing thr_join\n"); - - THROW_ERRORS(thr_join(sol_thread, (thread_t *)NULL, status)); - - DB(cerr << "omni_thread::join: thr_join succeeded\n"); - - delete this; -} - - -// -// Change this thread's priority. -// - -void -omni_thread::set_priority(priority_t pri) -{ - omni_mutex_lock l(mutex); - - if (_state != STATE_RUNNING) - throw omni_thread_invalid(); - - _priority = pri; - - THROW_ERRORS(thr_setprio(sol_thread, sol_priority(pri))); -} - - -// -// create - construct a new thread object and start it running. Returns thread -// object if successful, null pointer if not. -// - -// detached version - -omni_thread* -omni_thread::create(void (*fn)(void*), void* arg, priority_t pri) -{ - omni_thread* t = new omni_thread(fn, arg, pri); - - t->start(); - - return t; -} - -// undetached version - -omni_thread* -omni_thread::create(void* (*fn)(void*), void* arg, priority_t pri) -{ - omni_thread* t = new omni_thread(fn, arg, pri); - - t->start(); - - return t; -} - - -// -// exit() _must_ lock the mutex even in the case of a detached thread. This is -// because a thread may run to completion before the thread that created it has -// had a chance to get out of start(). By locking the mutex we ensure that the -// creating thread must have reached the end of start() before we delete the -// thread object. Of course, once the call to start() returns, the user can -// still incorrectly refer to the thread object, but that's their problem. -// - -void -omni_thread::exit(void* return_value) -{ - omni_thread* me = self(); - - if (me) - { - me->mutex.lock(); - - me->_state = STATE_TERMINATED; - - me->mutex.unlock(); - - DB(cerr << "omni_thread::exit: thread " << me->id() << " detached " - << me->detached << " return value " << return_value << endl); - - if (me->detached) - delete me; - } - else - { - DB(cerr << "omni_thread::exit: called with a non-omnithread. Exit quietly." << endl); - } - - thr_exit(return_value); -} - - -omni_thread* -omni_thread::self(void) -{ - omni_thread* me; - - THROW_ERRORS(thr_getspecific(self_key, (void**)&me)); - - if (!me) { - // This thread is not created by omni_thread::start because it - // doesn't has a class omni_thread instance attached to its key. - DB(cerr << "omni_thread::self: called with a non-ominthread. NULL is returned." << endl); - } - - return me; -} - - -void -omni_thread::yield(void) -{ - thr_yield(); -} - - -void -omni_thread::sleep(unsigned long secs, unsigned long nanosecs) -{ - timespec rqts = { secs, nanosecs }; - timespec remain; - while (nanosleep(&rqts, &remain)) { - if (errno == EINTR) { - rqts.tv_sec = remain.tv_sec; - rqts.tv_nsec = remain.tv_nsec; - continue; - } - else - throw omni_thread_fatal(errno); - } -} - - -void -omni_thread::get_time(unsigned long* abs_sec, unsigned long* abs_nsec, - unsigned long rel_sec, unsigned long rel_nsec) -{ - timespec abs; - clock_gettime(CLOCK_REALTIME, &abs); - abs.tv_nsec += rel_nsec; - abs.tv_sec += rel_sec + abs.tv_nsec / 1000000000; - abs.tv_nsec = abs.tv_nsec % 1000000000; - *abs_sec = abs.tv_sec; - *abs_nsec = abs.tv_nsec; -} - - -int -omni_thread::sol_priority(priority_t pri) -{ - switch (pri) { - - case PRIORITY_LOW: - return 0; - - case PRIORITY_NORMAL: - return 1; - - case PRIORITY_HIGH: - return 2; - } - - throw omni_thread_invalid(); -} - - -void -omni_thread::stacksize(unsigned long sz) -{ - stack_size = sz; -} - -unsigned long -omni_thread::stacksize() -{ - return stack_size; -} - - -// -// Dummy thread -// - -#error This dummy thread code is not tested. It might work if you're lucky. - -class omni_thread_dummy : public omni_thread { -public: - inline omni_thread_dummy() : omni_thread() - { - _dummy = 1; - _state = STATE_RUNNING; - sol_thread = thr_self(); - THROW_ERRORS(thr_setspecific(self_key, (void*)this)); - } - inline ~omni_thread_dummy() - { - THROW_ERRORS(thr_setspecific(self_key, 0)); - } -}; - -omni_thread* -omni_thread::create_dummy() -{ - if (omni_thread::self()) - throw omni_thread_invalid(); - - return new omni_thread_dummy; -} - -void -omni_thread::release_dummy() -{ - omni_thread* self = omni_thread::self(); - if (!self || !self->_dummy) - throw omni_thread_invalid(); - - omni_thread_dummy* dummy = (omni_thread_dummy*)self; - delete dummy; -} - - -#define INSIDE_THREAD_IMPL_CC -#include "threaddata.cc" -#undef INSIDE_THREAD_IMPL_CC diff --git a/omnithread/threaddata.cc b/omnithread/threaddata.cc deleted file mode 100644 index d54c4391..00000000 --- a/omnithread/threaddata.cc +++ /dev/null @@ -1,83 +0,0 @@ -// Package : omnithread -// omnithread/threaddata.cc Created : 10/2000 dpg1 -// -// Copyright (C) 2000 AT&T Laboratories Cambridge -// -// This file is part of the omnithread library -// -// The omnithread library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library 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 -// Library General Public License for more details. -// -// You should have received a copy of the GNU Library General Public -// License along with this library; if not, write to the Free -// Software Foundation, Inc., 51 Franklin Street, Boston, MA -// 02110-1301, USA -// - -// Implementation of per-thread data - -#ifndef INSIDE_THREAD_IMPL_CC -#error "threaddata.cc must be #included by a thread implementation." -#endif - - -static omni_thread::key_t allocated_keys = 0; - -omni_thread::key_t -omni_thread::allocate_key() -{ - omni_mutex_lock l(*next_id_mutex); - return ++allocated_keys; -} - -omni_thread::value_t* -omni_thread::set_value(key_t k, value_t* v) -{ - if (k == 0) return 0; - if (k > _value_alloc) { - next_id_mutex->lock(); - key_t alloc = allocated_keys; - next_id_mutex->unlock(); - - if (k > alloc) return 0; - - value_t** nv = new value_t*[alloc]; - key_t i = 0; - if (_values) { - for (; i < _value_alloc; i++) - nv[i] = _values[i]; - delete [] _values; - } - for (; i < alloc; i++) - nv[i] = 0; - - _values = nv; - _value_alloc = alloc; - } - if (_values[k-1]) delete _values[k-1]; - _values[k-1] = v; - return v; -} - -omni_thread::value_t* -omni_thread::get_value(key_t k) -{ - if (k > _value_alloc) return 0; - return _values[k-1]; -} - -omni_thread::value_t* -omni_thread::remove_value(key_t k) -{ - if (k > _value_alloc) return 0; - value_t* v = _values[k-1]; - _values[k-1] = 0; - return v; -} diff --git a/omnithread/vxWorks.cc b/omnithread/vxWorks.cc deleted file mode 100644 index aaff6cdb..00000000 --- a/omnithread/vxWorks.cc +++ /dev/null @@ -1,1160 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Filename: vxWorks.cc -// Author: Tihomir Sokcevic -// Acterna, Eningen. -// Description: vxWorks adaptation of the omnithread wrapper classes -// Notes: Munching strategy is imperative -////////////////////////////////////////////////////////////////////////////// -// $Log$ -// Revision 1.1 2004/04/10 18:00:52 eb -// Initial revision -// -// Revision 1.1.1.1 2004/03/01 00:20:27 eb -// initial checkin -// -// Revision 1.1 2003/05/25 05:29:04 eb -// see ChangeLog -// -// Revision 1.1.2.1 2003/02/17 02:03:11 dgrisby -// vxWorks port. (Thanks Michael Sturm / Acterna Eningen GmbH). -// -// Revision 1.1.1.1 2002/11/19 14:58:04 sokcevti -// OmniOrb4.0.0 VxWorks port -// -// Revision 1.4 2002/10/15 07:54:09 kuttlest -// change semaphore from SEM_FIFO to SEM_PRIO -// --- -// -// Revision 1.3 2002/07/05 07:38:52 engeln -// made priority redefinable on load time by defining int variables -// omni_thread_prio_low = 220; -// omni_thread_prio_normal = 110; -// omni_thread_prio_high = 55; -// the default priority is prio_normal. -// The normal priority default has been increased from 200 to 110 and the -// high priority from 100 to 55. -// --- -// -// Revision 1.2 2002/06/14 12:44:57 engeln -// replaced possibly unsafe wakeup procedure in broadcast. -// --- -// -// Revision 1.1.1.1 2002/04/02 10:09:34 sokcevti -// omniORB4 initial realease -// -// Revision 1.0 2001/10/23 14:22:45 sokcevti -// Initial Version 4.00 -// --- -// -////////////////////////////////////////////////////////////////////////////// - - -////////////////////////////////////////////////////////////////////////////// -// Include files -////////////////////////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include - -#include // assert -#include // intContext - - -////////////////////////////////////////////////////////////////////////////// -// Local defines -////////////////////////////////////////////////////////////////////////////// -#define ERRNO(x) (((x) != 0) ? (errno) : 0) -#define THROW_ERRORS(x) { if((x) != OK) throw omni_thread_fatal(errno); } -#define OMNI_THREAD_ID 0x7F7155AAl -#define OMNI_STACK_SIZE 32768l - -#ifdef _DEBUG - #include - #define DBG_TRACE(X) X -#else // _DEBUG - #define DBG_TRACE(X) -#endif // _DEBUG - -#define DBG_ASSERT(X) - -#define DBG_THROW(X) X - -int omni_thread_prio_low = 220; -int omni_thread_prio_normal = 110; -int omni_thread_prio_high = 55; -/////////////////////////////////////////////////////////////////////////// -// -// Mutex -// -/////////////////////////////////////////////////////////////////////////// -omni_mutex::omni_mutex(void):m_bConstructed(false) -{ - mutexID = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE); - - DBG_ASSERT(assert(mutexID != NULL)); - - if(mutexID==NULL) - { - DBG_TRACE(cout<<"Exception: omni_mutex::omni_mutex() tid: "<<(int)taskIdSelf()<mutexID<<" tid:"<<(int)taskIdSelf()<mutexID<<" tid:"<<(int)taskIdSelf()< count. - - STATUS status = semTake(waiters_lock_,WAIT_FOREVER); - - DBG_ASSERT(assert(status == OK)); - - if(status != OK) - { - DBG_TRACE(cout<<"Exception: omni_condition::wait"<unlock(); - - // Wait to be awakened by a cond_signal() or cond_broadcast(). - status = semTake(sema_,WAIT_FOREVER); - - // reenable task rescheduling - taskUnlock(); - - DBG_ASSERT(assert(status == OK)); - - if(status != OK) - { - DBG_TRACE(cout<<"Exception: omni_condition::wait"< count. - status = semTake(waiters_lock_,WAIT_FOREVER); - - DBG_ASSERT(assert(status == OK)); - - if(status != OK) - { - DBG_TRACE(cout<<"Exception: omni_condition::wait"<, even when errors - // occur because that's the guarantee that we give to our callers. - mutex->lock(); -} - - -// The time given is absolute. Return 0 is timeout -int omni_condition::timedwait(unsigned long secs, unsigned long nanosecs) -{ - STATUS result = OK; - timespec now; - unsigned long timeout; - int ticks; - - // Prevent race conditions on the count. - STATUS status = semTake(waiters_lock_, WAIT_FOREVER); - - DBG_ASSERT(assert(status == OK)); - - if(status != OK) - { - DBG_TRACE(cout<<"Exception: omni_condition::timedwait"<unlock(); - - // Wait to be awakened by a signal() or broadcast(). - ticks = (timeout * sysClkRateGet()) / 1000L; - result = semTake(sema_, ticks); - - // reenable task rescheduling - taskUnlock(); - - // Reacquire lock to avoid race conditions. - status = semTake(waiters_lock_, WAIT_FOREVER); - - DBG_ASSERT(assert(status == OK)); - - if(status != OK) - { - DBG_TRACE(cout<<"Exception: omni_condition::timedwait"<id()<<" SemID:"<<(int)sema_<<" errno:"<, even when errors - // occur because that's the guarantee that we give to our callers. - mutex->lock(); - - if(result!=OK) // timeout - return 0; - - return 1; -} - -void omni_condition::signal(void) -{ - DBG_TRACE(cout<<"omni_condition::signal mutexID: "<<(int)mutex->mutexID<<" tid:"<<(int)taskIdSelf()< 0; - - status = semGive(waiters_lock_); - - DBG_ASSERT(assert(status == OK)); - - if(status != OK) - { - DBG_TRACE(cout<<"Exception: omni_condition::signal"<mutexID<<" tid:"<<(int)taskIdSelf()< must be locked before this call is made. - // This is needed to ensure that and are - // consistent relative to each other. - STATUS status = semTake(waiters_lock_, WAIT_FOREVER); - - DBG_ASSERT(assert(status == OK)); - - if(status != OK) - { - DBG_TRACE(cout<<"Exception: omni_condition::signal"< 0) - { - // We are broadcasting, even if there is just one waiter... - // Record the fact that we are broadcasting. This helps the - // cond_wait() method know how to optimize itself. Be sure to - // set this with the held. - have_waiters = 1; - } - - status = semGive(waiters_lock_); - - DBG_ASSERT(assert(status == OK)); - - if(status != OK) - { - DBG_TRACE(cout<<"Exception: omni_condition::signal"<id()<<" SemID:"<<(int)sema_<<" errno:"<spare1 = 0; - delete self; - - delete next_id_mutex; -} - - -// -// Wrapper for thread creation. -// -extern "C" void omni_thread_wrapper(void* ptr) -{ - omni_thread* me = (omni_thread*)ptr; - - DBG_TRACE(cout<<"omni_thread_wrapper: thread "<id()<<" started\n"); - - // - // We can now tweaked the task info since the tcb exist now - // - me->mutex.lock(); // To ensure that start has had time to finish - taskTcb(me->tid)->spare1 = OMNI_THREAD_ID; - taskTcb(me->tid)->spare2 = (int)ptr; - me->mutex.unlock(); - - // - // Now invoke the thread function with the given argument. - // - if(me->fn_void != NULL) - { - (*me->fn_void)(me->thread_arg); - omni_thread::exit(); - } - - if(me->fn_ret != NULL) - { - void* return_value = (*me->fn_ret)(me->thread_arg); - omni_thread::exit(return_value); - } - - if(me->detached) - { - me->run(me->thread_arg); - omni_thread::exit(); - } - else - { - void* return_value = me->run_undetached(me->thread_arg); - omni_thread::exit(return_value); - } -} - - -// -// Special functions for VxWorks only -// -void omni_thread::attach(void) -{ - DBG_TRACE(cout<<"omni_thread_attach: VxWorks mapping thread initialising\n"); - - int _tid = taskIdSelf(); - - // Check the task is not already attached - if(taskTcb(_tid)->spare1 == OMNI_THREAD_ID) - return; - - // Create the mutex required to lock the threads debugging id (create before the thread!!!) - if(next_id_mutex == 0) - next_id_mutex = new omni_mutex; - - // Create a thread object for THIS running process - omni_thread* t = new omni_thread; - - // Lock its mutex straigh away! - omni_mutex_lock l(t->mutex); - - // Adjust data members of this instance - t->_state = STATE_RUNNING; - t->tid = taskIdSelf(); - - // Set the thread values so it can be recongnised as a omni_thread - // Set the id last can possibly prevent race condition - taskTcb(t->tid)->spare2 = (int)t; - taskTcb(t->tid)->spare1 = OMNI_THREAD_ID; - - // Create the running_mutex at this stage, but leave it empty. We are not running - // in the task context HERE, so taking it would be disastrous. - t->running_cond = new omni_condition(&t->mutex); -} - - -void omni_thread::detach(void) -{ - DBG_TRACE(cout<<"omni_thread_detach: VxWorks detaching thread mapping\n"); - - int _tid = taskIdSelf(); - - // Check the task has a OMNI_THREAD attached - if(taskTcb(_tid)->spare1 != OMNI_THREAD_ID) - return; - - // Invalidate the id NOW ! - taskTcb(_tid)->spare1 = 0; - - // Even if NULL, it is safe to delete the thread - omni_thread* t = (omni_thread*)taskTcb(_tid)->spare2; - // Fininsh cleaning the tcb structure - taskTcb(_tid)->spare2 = 0; - - delete t; -} - - -// -// Constructors for omni_thread - set up the thread object but don't -// start it running. -// - -// construct a detached thread running a given function. -omni_thread::omni_thread(void (*fn)(void*), void* arg, priority_t pri) -{ - common_constructor(arg, pri, 1); - fn_void = fn; - fn_ret = NULL; -} - -// construct an undetached thread running a given function. -omni_thread::omni_thread(void* (*fn)(void*), void* arg, priority_t pri) -{ - common_constructor(arg, pri, 0); - fn_void = NULL; - fn_ret = fn; -} - -// construct a thread which will run either run() or run_undetached(). - -omni_thread::omni_thread(void* arg, priority_t pri) -{ - common_constructor(arg, pri, 1); - fn_void = NULL; - fn_ret = NULL; -} - -// common part of all constructors. -void omni_thread::common_constructor(void* arg, priority_t pri, int det) -{ - _state = STATE_NEW; - _priority = pri; - - // Set the debugging id - next_id_mutex->lock(); - _id = next_id++; - next_id_mutex->unlock(); - - // Note : tid can only be setup when the task is up and running - tid = 0; - - thread_arg = arg; - detached = det; // may be altered in start_undetached() - - _dummy = 0; - _values = 0; - _value_alloc = 0; -} - -// -// Destructor for omni_thread. -// -omni_thread::~omni_thread(void) -{ - DBG_TRACE(cout<<"omni_thread::~omni_thread for thread "<wait(); - mutex.unlock(); - - if(status) - *status = return_val; - - delete this; -} - - -// -// Change this thread's priority. -// -void omni_thread::set_priority(priority_t pri) -{ - omni_mutex_lock l(mutex); - - DBG_ASSERT(assert(_state == STATE_RUNNING)); - - if(_state != STATE_RUNNING) - { - DBG_THROW(throw omni_thread_invalid()); - } - - _priority = pri; - - if(taskPrioritySet(tid, vxworks_priority(pri))==ERROR) - { - DBG_ASSERT(assert(false)); - - DBG_THROW(throw omni_thread_fatal(errno)); - } -} - - -// -// create - construct a new thread object and start it running. Returns thread -// object if successful, null pointer if not. -// - -// detached version (the entry point is a void) -omni_thread* omni_thread::create(void (*fn)(void*), void* arg, priority_t pri) -{ - omni_thread* t = new omni_thread(fn, arg, pri); - - t->start(); - - return t; -} - -// undetached version (the entry point is a void*) -omni_thread* omni_thread::create(void* (*fn)(void*), void* arg, priority_t pri) -{ - omni_thread* t = new omni_thread(fn, arg, pri); - - t->start(); - - return t; -} - - -// -// exit() _must_ lock the mutex even in the case of a detached thread. This is -// because a thread may run to completion before the thread that created it has -// had a chance to get out of start(). By locking the mutex we ensure that the -// creating thread must have reached the end of start() before we delete the -// thread object. Of course, once the call to start() returns, the user can -// still incorrectly refer to the thread object, but that's their problem. -// -void omni_thread::exit(void* return_value) -{ - omni_thread* me = self(); - - if(me) - { - me->mutex.lock(); - - me->return_val = return_value; - me->_state = STATE_TERMINATED; - me->running_cond->signal(); - - me->mutex.unlock(); - - DBG_TRACE(cout<<"omni_thread::exit: thread "<id()<<" detached "<detached<<" return value "<<(int)return_value<detached) - delete me; - } - else - DBG_TRACE(cout<<"omni_thread::exit: called with a non-omnithread. Exit quietly."<spare1 != OMNI_THREAD_ID) - return NULL; - - return (omni_thread*)taskTcb(taskIdSelf())->spare2; -} - - -void omni_thread::yield(void) -{ - taskDelay(NO_WAIT); -} - - -void omni_thread::sleep(unsigned long secs, unsigned long nanosecs) -{ - int tps = sysClkRateGet(); - - // Convert to us to avoid overflow in the multiplication - // tps should always be less than 1000 ! - nanosecs /= 1000; - - taskDelay(secs*tps + (nanosecs*tps)/1000000l); -} - - -void omni_thread::get_time( unsigned long* abs_sec, - unsigned long* abs_nsec, - unsigned long rel_sec, - unsigned long rel_nsec) -{ - timespec abs; - clock_gettime(CLOCK_REALTIME, &abs); - abs.tv_nsec += rel_nsec; - abs.tv_sec += rel_sec + abs.tv_nsec / 1000000000; - abs.tv_nsec = abs.tv_nsec % 1000000000; - *abs_sec = abs.tv_sec; - *abs_nsec = abs.tv_nsec; -} - - -int omni_thread::vxworks_priority(priority_t pri) -{ - switch (pri) - { - case PRIORITY_LOW: - return omni_thread_prio_low; - - case PRIORITY_NORMAL: - return omni_thread_prio_normal; - - case PRIORITY_HIGH: - return omni_thread_prio_high; - } - - DBG_ASSERT(assert(false)); - - DBG_THROW(throw omni_thread_invalid()); -} - - -void omni_thread::stacksize(unsigned long sz) -{ - stack_size = sz; -} - - -unsigned long omni_thread::stacksize() -{ - return stack_size; -} - - -void omni_thread::show(void) -{ - omni_thread *pThread; - int s1, s2; - int tid = taskIdSelf(); - - printf("TaskId is %.8x\n", tid); - - s1 = taskTcb(tid)->spare1; - - if(s1 != OMNI_THREAD_ID) - { - printf("Spare 1 is %.8x, and not recongnized\n", s1); - - return; - } - else - { - printf("Spare 1 indicate an omni_thread.\n"); - } - - s2 = taskTcb(tid)->spare2; - - if(s2 == 0) - { - printf("Spare 2 is NULL! - No thread object attached !!\n"); - - return; - } - else - { - printf("Thread object at %.8x\n", s2); - } - - pThread = (omni_thread *)s2; - - state_t status = pThread->_state; - - printf(" | Thread status is "); - - switch (status) - { - case STATE_NEW: - printf("NEW\n"); break; - case STATE_RUNNING: - printf("STATE_RUNNING\n"); break; - case STATE_TERMINATED: - printf("TERMINATED\n"); break; - default: - printf("Illegal (=%.8x)\n", (unsigned int)status); - - return; - } - - if(pThread->tid != tid) - { - printf(" | Task ID in thread object is different!! (=%.8x)\n", pThread->tid); - - return; - } - else - { - printf(" | Task ID in thread consistent\n"); - } - - printf("\n"); -} - - -// -// Dummy thread -// - -class omni_thread_dummy : public omni_thread { -public: - inline omni_thread_dummy() : omni_thread() - { - _dummy = 1; - _state = STATE_RUNNING; - - // Adjust data members of this instance - tid = taskIdSelf(); - - // Set the thread values so it can be recongnised as a omni_thread - // Set the id last can possibly prevent race condition - taskTcb(tid)->spare2 = (int)this; - taskTcb(tid)->spare1 = OMNI_THREAD_ID; - } - inline ~omni_thread_dummy() - { - taskTcb(taskIdSelf())->spare1 = 0; - } -}; - -omni_thread* -omni_thread::create_dummy() -{ - if (omni_thread::self()) - throw omni_thread_invalid(); - - return new omni_thread_dummy; -} - -void -omni_thread::release_dummy() -{ - omni_thread* self = omni_thread::self(); - if (!self || !self->_dummy) - throw omni_thread_invalid(); - - omni_thread_dummy* dummy = (omni_thread_dummy*)self; - delete dummy; -} - - -#define INSIDE_THREAD_IMPL_CC -#include "threaddata.cc" -#undef INSIDE_THREAD_IMPL_CC diff --git a/usrp2/host/usrp2.pc.in b/usrp2/host/usrp2.pc.in index eaef5f41..e0c2b198 100644 --- a/usrp2/host/usrp2.pc.in +++ b/usrp2/host/usrp2.pc.in @@ -5,7 +5,7 @@ includedir=@includedir@ Name: usrp2 Description: Universal Software Radio Peripheral 2 -Requires: gnuradio-omnithread gruel +Requires: gruel Version: @VERSION@ Libs: -L${libdir} -lusrp2 Cflags: -I${includedir} @DEFINES@ -- 2.39.5