home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1997 December / Internet_Info_CD-ROM_Walnut_Creek_December_1997.iso / faqs / comp / answers / chorus-faq < prev    next >
Text File  |  1997-10-10  |  44KB  |  976 lines

  1. Newsgroups: comp.os.chorus,news.answers,comp.answers
  2. Path: senator-bedfellow.mit.edu!bloom-beacon.mit.edu!eru.mt.luth.se!luth.se!news.algonet.se!uninett.no!newsfeed.nacamar.de!eerie.fr!Cabal.CESspool!bofh.vszbr.cz!lyra.csx.cam.ac.uk!server1.netnews.ja.net!warwick!bris.ac.uk!bath.ac.uk!dcl-cs!pr
  3. From: pr@comp.lancs.ac.uk (Philippe Robin)
  4. Subject: comp.os.chorus Frequently Asked Questions (FAQ)
  5. Message-ID: <chorus-faq_876403043@comp.lancs.ac.uk>
  6. Followup-To: comp.os.chorus
  7. Summary: This posting contains a list of Frequently Asked Questions 
  8.          (and their answers) about the CHORUS microkernel technology.
  9. Keywords: CHORUS
  10. Sender: usenet@comp.lancs.ac.uk
  11. Supersedes: <chorus-faq_871308581@comp.lancs.ac.uk>
  12. Nntp-Posting-Host: columbine.comp.lancs.ac.uk
  13. Reply-To: pr@comp.lancs.ac.uk
  14. Cc: pr@comp.lancs.ac.uk
  15. Organization: Lancaster University - UK-
  16. Date: Thu, 9 Oct 1997 12:45:28 GMT
  17. Maintainer: <chorus-adm@comp.lancs.ac.uk> "Philippe Robin"
  18. Approved: news-answers-request@mit.edu
  19. Expires: Mon, 22 Dec 1997 13:17:23 GMT
  20. Lines: 953
  21. Xref: senator-bedfellow.mit.edu comp.os.chorus:597 news.answers:114188 comp.answers:28449
  22.  
  23. Posting-Frequency: bi-monthly
  24. Archive-name: chorus-faq
  25. Last-modified: 1997/10/09
  26. Revision: 1.30
  27.  
  28. Changes from last posting:
  29.  
  30.   + Added section 6 containing Q&A on other software.
  31.   + Added section 5.4 for Q&A on CHORUS/ClassiX
  32.   + Few Q&A in section 5.3 about CHORUS/COOL.
  33.  
  34. ----------------
  35.  
  36.         Table of Contents
  37.         =================
  38.  
  39. 1. General Information
  40.     1.1. Organization and Availability of this FAQ
  41.     1.2. What's New?
  42.     1.3. What is CHORUS?
  43.     1.4. How to Contact Chorus Systems?
  44.     1.5. Disclaimer & Copyright
  45. 2. Documentation
  46.     2.1. Documentation Available through Anonymous FTP
  47.     2.2. Papers on CHORUS
  48.     2.3. Other references
  49.     2.4. Press references
  50. 3. Chorus Product Offering
  51.     3.1. Overview
  52.     3.2. Offering for Universities
  53. 4. CHORUS Microkernel
  54.     4.1. General
  55.     4.2. Supported Microprocessors
  56.     4.3. Porting on various platforms
  57.     4.4. Scheduling and real-time
  58.     4.5. CHORUS on Transputers
  59.     4.6. Comparison with other OS
  60.     4.7. Perfomances
  61.     4.8. Object Oriented issues
  62. 5. OS Personalities
  63.     5.1. OS personalities available on top of CHORUS
  64.     5.2. CHORUS/MiX V.3.2
  65.     5.3. CHORUS/COOL-ORB
  66.     5.4. CHORUS/ClassiX
  67. 6. Other Software
  68.     --------------
  69.  
  70. 1. General Information
  71.    ===================
  72. 1.1. Organization and Availability of this FAQ
  73.      -----------------------------------------
  74.   This FAQ contains informations related to the CHORUS operating system,
  75. description of the products and contacts. It will be progressively 
  76. updated according to the discussions held in this newsgroup and the 
  77. evolution of the products.
  78.  
  79.   It is posted every two months in the following newsgroups:<<comp.os.chorus, 
  80. news.answers, comp.answers >>. A Japanese version of the FAQ is also available 
  81. in the <<fj.os.misc>> newsgroup. Copies of the FAQ can also be obtained by 
  82. e-mail by sending a request to "chorus-adm@comp.lancs.ac.uk". Hypertext
  83. version of the FAQ can be found at the following URLs:
  84.  
  85.     http://www.comp.lancs.ac.uk/computing/users/pr/www/chorus/faq.html
  86.     http://www.faqs.org
  87.  
  88.   You can make any comments, suggestions or contributions to this 
  89. FAQ by sending an e-mail to "chorus-adm@comp.lancs.ac.uk" or 
  90. "pr@comp.lancs.ac.uk" or by discussions in the newsgroup.
  91.  
  92. 1.2. What's New?
  93.      -----------
  94.   Added section 6 containing Q&A on other software.
  95.   Added section 5.4 for Q&A on CHORUS/ClassiX
  96.   Few Q&A in section 5.3 about CHORUS/COOL.
  97.  
  98. 1.3. What is CHORUS?
  99.      --------------
  100.   CHORUS is a family of open microkernel-based operating system
  101. components to meet advanced distributed computing needs in areas such
  102. as telecommunications, internetworking, embedded systems, realtime,
  103. "mainframe UNIX", supercomputing and high availability. The CHORUS/MiX
  104. multiserver implementations of UNIX allow to dynamically integrate
  105. part or all of standard UNIX functionalities and services in the above
  106. application areas.
  107.  
  108.   CHORUS is designed, developed and marketed by Chorus Systems.
  109.  
  110.  
  111. 1.4. How to Contact Chorus Systems
  112.      -----------------------------
  113.      North America:
  114.     Chorus Systems Inc.
  115.     1999 South Bascom Avenue, Suite 400
  116.     Campbell, CA 95008
  117.     United States
  118.     Phone: +1 (408) 879-4100
  119.     Fax:   +1 (408) 879-4102
  120.     Voice Mail:  +1 (408) 291 8832
  121.     Email: info@chorus.com
  122.  
  123.      Europe:
  124.     Chorus systemes SA
  125.     6 avenue Gustave Eiffel
  126.     F-78182 St Quentin-en-Yvelines Cedex
  127.     France                        
  128.     Phone: +33 (1) 30 64 82 00        
  129.     Fax:   +33 (1) 30 57 00 66        
  130.     Email: info@chorus.fr         
  131.  
  132.      Asia Pacific:
  133.     Chorus Systems KK
  134.     Mitsutake Building Ikejiri, 8F
  135.     3-22-4 Ikejiri, Setagaya Ku
  136.     Tokyo 154
  137.     Japan
  138.     Phone: +81 (3) 5430-1131
  139.     Fax:   +81 (3) 5430-1133
  140.     Email: info-ap@chorus.com
  141.  
  142. 1.4. Disclaimer & Copyright
  143.      ---------------------
  144.   The author provides no warranty regarding the content of this document. 
  145. It is provided "as is" without express or implied waranty.
  146.  
  147.   Permisson to distribute this document, in part or full, via electronic
  148. means (emailed, posted or archived) or printed copy are granted providing
  149. that no charges are involved, reasonable attempt is made to use the most
  150. current version, and all credits notices are retained. For other distributions
  151. including incorporation in commercial products, such as books, magazine 
  152. articles, or CD-ROMs, you must get permission from the author first 
  153. (e-mail: chorus-adm@comp.lancs.ac.uk). 
  154.  
  155. 2. Documentation
  156.    =============
  157. 2.1. Documentation Available through Anonymous FTP
  158.      ---------------------------------------------
  159.   There are several technical reports on CHORUS available via anonymous
  160. FTP from Chorus systemes, France: ftp.chorus.fr [192.33.15.3],
  161. directory pub/chorus-reports (see the file "index" for an overview).
  162. A set of slides on CHORUS is also available in the directory 
  163. "pub/chorus-slides", documents CS-TR-92-64 (PostScript, versions 1-up 
  164. and 2-up). 
  165.  
  166.   Product Data Sheets are available (in ascii or PostScript format) in
  167. the directory "pub/chorus-datasheets".
  168.  
  169.   Those reports are available through the World Wide Web at Chorus 
  170. systemes: "ftp://ftp.chorus.fr/pub" or from the Web server at the 
  171. URL:"http://www.chorus.com".
  172.  
  173. 2.2. Papers on CHORUS
  174.      ----------------
  175. [Bricker, 1991] A. Bricker, M. Gien, M. Guillemont, J. Lipkis, D. Orr and
  176. M. Rozier, "A new look at micro-kernel-based UNIX operating systems:
  177. Lessons in performance and compatibility". Proc. of the EurOpen Spring'91 
  178. Conference, Tromsoe, Norway, 20-24 May 1991.
  179. Chorus Systems Technical Report CS-TR-91-7
  180.  
  181. [Coulson, 1994] Coulson G., and G.S. Blair. "Microkernel Support for 
  182. Continuous Media in Distributed Systems". Computer Networks and ISDN
  183. Systems, Special Issue on Multimedia, 1994; also available as internal
  184. report MPG-93-04, Computing Dept., Lancaster University.
  185.  
  186. [Gaultier, 1994] O. Gautier and Y. Metais. "Mise en Place d'une Plateforme
  187. CHORUS, Conception et Implementation d'un Ordonnanceur a Echeance au Sein 
  188. du Noyau Chorus". Memoire CNAM, Paris, March 1994.
  189.  
  190. CS/TR-94-82.1 "CHORUS Kernel v3 r5 for T425/T805 Connection Manager and
  191.         Aserver Library" (Internal Report)
  192.  
  193. CS/TR-94-81.1 "CHORUS Kernel v3 r5 for T425/T805 Host Server User's
  194.         Manual, Aserver Guide" (Internal Report)
  195.  
  196. 2.3. Other references
  197.      ----------------
  198. [Bradley, 1993] J Bradley Chen and Brian N Bershad
  199. "The Impact of Operating System Structure on Memory System Performance",
  200. ACM SIGOPS Dec. '93
  201.  
  202. [Coulouris, 1994] G. Coulouris, J. Dollimore and T. Kindberg. "Distributed
  203. Systems, Concepts and Design", Addison-Wesley, second edition, 1994.
  204.  
  205. [Douglis et al., 1992] Douglis, F., Kaashoek, M.F., and Tanenbaum,
  206. A.S.: "A Comparison of Two Distributed Systems: Amoeba and Sprite,"
  207. Computing Systems, vol. 4, Fall 1991 (sic).
  208.  
  209. [Dean, 1992] R. Dean and F. Armand. "Data Movement in Kernelized Systems".
  210. Proceedings of the USENIX Workshop on Micro-Kernels and Other Kernel 
  211. Architectures, pp. 243-261, April 1992.
  212.  
  213. [Tanenbaum, 1992]  Andrew S. Tanenbaum: "Modern Operating Systems",
  214. Prentice-Hall, 1992.
  215.  
  216. [Tanenbaum, 1994] Andrew S. Tanenbaum, "Distributed Operating Systems", 
  217. Prentice-Hall, ISBN 0-13-219908-4
  218.  
  219. [Tanenbaum, 1995] Andrew S. Tananbaum, "A Comparison of Three Microkernels",
  220. The Journal of Supercomputing, vol 9, number 1, ISSN 0920-8542, 1995.
  221.  
  222. 2.4. Press references
  223.      ----------------
  224. BYTE, Jan 94 issue:
  225.       - "Small Kernels Hit it Big" (by Peter Varhol, p. 119, 6 pages), and
  226.       - "The Chorus Microkernel" (by Dick Pountain, p. 131, 4 pages)
  227.     (a color reprint of these articles is available upon request
  228.     from Chorus Systems.)
  229.  
  230. BYTE, Feb 95 issue:
  231.       - "Novell's Campaign" (by Jon Udell, p. 43, 11 pages)
  232.     CHORUS is mentioned in this article as being the basis for
  233.     the microkernel underpinning the UnixWare and NetWare personalities.
  234.  
  235. BYTE, Mar 95 issue:
  236.       - "Europe's Chip Challenge" (by Dick Pountain, p. 19, 5 pages)
  237.     CHORUS is mentioned in this article on the CEC's Open Microprocessor
  238.     Initiative (OMI) as the microkernel being used and enhanced within
  239.     various OMI projects.
  240.  
  241. 3. Chorus Product Offering
  242.    =======================
  243. 3.1. Overview
  244.      --------
  245.  
  246.   The CHORUS/Nucleus v3 is a realtime distributed microkernel. The Nucleus 
  247. provides a unified virtual machine interface for various operating system 
  248. (subsystem) implementations. Each subsystem implements one operating system 
  249. interface by using the Nucleus services. A complete description of this 
  250. product can be found at the following URL: 
  251. http://www.chorus.com/Products/Datasheets/nucleusv3.html
  252.  
  253.   CHORUS/Simulator is a port of the CHORUS microkernel on top of UNIX.
  254. It runs as a UNIX process, e.g. under SunOS 4.1 or Solaris 2.3 on a 
  255. Sun SPARCstation, and allows one to develop and test applications using 
  256. the microkernel's API.
  257.  
  258.   CHORUS/MiX V.4 is a distributed multi-server implementation of 
  259. UNIX SVR4.0 on top of the CHORUS microkernel). E.g. on a 386/486 PC/AT, 
  260. it offers binary compatibility with native SVR4.0v4. MiX V.4 requires a  
  261. Novell/USG SVR4.0 source license. More information on this product can
  262. be found at http://www.chorus.com/Products/Datasheets/mixv4.html.
  263.  
  264.   CHORUS/Fusion for SCO Open Systems Software is a multi-server
  265. implementation of SCO UNIX and extends it with realtime functionality 
  266. (POSIX 1003.1b and .1c, i.e.  the former .4 and .4a interfaces) and 
  267. clustering functionality.  CHORUS/Fusion is developed and marketed 
  268. jointly by SCO and Chorus on Intel-based PC's. More information on 
  269. this product can be found at the following URL:
  270. http://www.chorus.com/Products/Datasheets/fusion.html
  271.  
  272.   CHORUS/COOL is a distributed programming environment for object-oriented
  273. applications. CHORUS/COOL supports the dynamic creation of C++ objects,
  274. these objects can be invoked, using C++ mechanism in a system wide
  275. transparent way. Objects can migrate, and remain persistent unless
  276. explicitly deleted.  The programming model used is based on the Object
  277. Management Group's architecture (OMG). 
  278.  
  279.   CHORUS/COOL-ORB is an OMG-CORBA compliant Object Request Broker. It is
  280. available for CHORUS/Fusion, CHORUS/ClassiX, CHORUS/MiX V.4, SCO UNIX,
  281. SunOS 4.1, Solaris, Linux, AIX, Windows95 and WindowsNT. More information 
  282. concerning this product can be found at the following URL: 
  283. http://www.chorus.com/Products/Datasheets/coolorb.html
  284.  
  285.   CHORUS/ClassiX is host-target cross-development environment for
  286. C++ or C written applications, named C_actors. C_actors can be loaded,
  287. unloaded and debugged dynamically from the host (e.g. SPARCstation/SunOS) 
  288. on the target (e.g. ix86 PC/AT), interconnected via Ethernet. 
  289. C_actor applications can interoperate with UNIX on the host
  290. through TCP/IP sockets and NFS. On the target, there is only the
  291. CHORUS/Nucleus microkernel and the CHORUS/C_actor subsystem but
  292. no CHORUS/MiX UNIX System V subsystem.
  293. CHORUS/ClassiX is available for i386/i486/Pentium (PC/AT), mc68040
  294. (MVME167), mc68360 (QUADS) Micro-SPARC-1/-2 (FORCE CPU-3CE/-5CE,
  295. SPARCclassic, SPARCstation 5, SPARCengine 5) and T425/T805/T9000
  296. (SGS-Thomson INMOS boards).  More informations can be found at the
  297. following URL: http://www.chorus.com/Products/Datasheets/classix.html.
  298.  
  299.   CHORUS/JaZZ is an implementation of the Java runtime and selected 
  300. components of the JavaOS that have been integrated into CHORUS/ClassiX 
  301. as an operating system personality. CHORUS/JaZZ extends CHORUS/ClassiX
  302. with a Java "Virtual Machine" personality including all standard Java 
  303. containers and classes such as windows, threads, I/O, exceptions and 
  304. network. More information on this product can be found at the following
  305. URL: http://www.chorus.com/Products/Datasheets/jazz.html.
  306.  
  307. 3.2. Offering for Universities
  308.      -------------------------
  309.   Chorus Systems has special programs for universities. More information 
  310. on offerings, conditions, etc is available via ftp (ftp://ftp.chorus.fr)
  311. in the following ASCII files:
  312.     - pub/README
  313.     - pub/academic/README
  314.     - pub/academic/offerings
  315.  
  316.   If you have questions, you may contact Didier.Irlande@chorus.fr.
  317.  
  318.  
  319. 4. CHORUS Microkernel
  320.    ==================
  321. 4.1. General
  322.      -------
  323.     * What is a microkernel?
  324.     A "microkernel" is an operating system with only the essential services, 
  325.     such as interprocess communication, short-term scheduling, and memory 
  326.     management.  It basically provides the process abstraction and a means 
  327.     for processes to communicate. It is designed to be portable between 
  328.     computer architectures, using high-level languages such as C or C++ and
  329.     reducing the machine-dependant component to a minimal bottom layer.
  330.     The microkernel appears as a layer between the hardware layer and a 
  331.     layer consisting of system components called 'subsystems'.
  332.     Their size can vary from about 10Kb to several hundred kilobytes 
  333.     of executable code and static data.
  334.  
  335.     * Synchronisation primitives offered to CHORUS threads?
  336.     The CHORUS microkernel (v3 r5.x) offers the following synchronisation
  337.     primitives:
  338.     - mutexes
  339.     - (counting) sempahores
  340.     - spin locks (supervisor applications only)
  341.     - mini messages (supervisor applications only)
  342.  
  343.     Other synchronisation primitives such as condition variables and
  344.     reader/writer locks can be built on top of those basic primitives.
  345.  
  346.     * Do CHORUS threads support specific data?
  347.     Yes. The microkernel supports so-called "software registers".
  348.     Each thread has two software registers which are systematically 
  349.     saved/restored by the microkernel upon a thread context switch. 
  350.     The software registers can be read/written through threadStoreR(K) 
  351.     and threadLoad(K) system calls.
  352.     A software register typically contains a pointer to a per-thread
  353.     private data area. Via software registers, one can implement e.g.
  354.     a per-thread value of "errno".
  355.  
  356.     * Distributed synchronization service on top of the CHORUS microkernel?
  357.     This work is part of a PhD thesis undertaken by Stephane Eranian 
  358.     <eranian@chorus.fr> implementing distributed synchronization service on 
  359.     top of the CHORUS microkernel. It implements pure mutex (no mr/sw).
  360.     The synchronization is achieved using a token-based algorithm through
  361.     a server. Its main role is to manage token creation, deletion and sharing 
  362.     among sets of clients. For more information contact S. Eranian.
  363.  
  364.     * Initialization of the context of an actor created with the actorCreate(K)
  365.     system call?
  366.  
  367.     To create an actor in CHORUS using actorCreate(K), the actor address
  368.     space must be empty (i.e. does not include any valid memory region). 
  369.     If you want to "fork" an actor, i.e. the new actor's code and data is
  370.     a copy of the main actor's code and data.
  371.  
  372.     In order perform address space duplication, you can use the rgnDup(K) 
  373.     service, just after having created the actor (and before having created
  374.     new regions: this operation is only valid on an empty address space).
  375.  
  376.     Before invoking rgnDup(K), you must specify for each region how the region
  377.     will be "duplicated": map (sharing), copy or not duplicated at all.
  378.     In order to do this, you have to get the list of your regions
  379.     (rgnStat(K)), and set the inheritance flags using rgnSetInherit(K).
  380.  
  381.     Note: an alternative to the rgnSetInherit/rgnDup scheme is to treat each 
  382.     region individually, using rgnMapFromActor(K) for shared regions,
  383.     and rgnInitFromActor(K) for copied regions.
  384.  
  385.     * Encryption mechanisms in CHORUS IPC?
  386.     CHORUS IPC does not provide any "encryption" mechanisms. Such mechanisms
  387.     can be implemented by applications.
  388.  
  389.     *  Given a set of actors and ports, what would happen if
  390.     one of the actors is stopped (with an actorStop) prior to an ipcSend().
  391.     Would all the other members of the port group receive the message or 
  392.     would the behavior of the kernel be different ?
  393.  
  394.     Depends on the mode set for the group, but if the group is in
  395.     broadcast mode all the members of the group should receive the message,
  396.     including ports belonging to actors in stopped state.
  397.  
  398.     *  Trap connection in supervisor actors using svTrapConnect(K) or 
  399.     scCallConnect(K)?
  400.  
  401.     - svCallConnect(int trapNb, KnCallEntry *table, uint entNb, int flag);
  402.     Connects a trap handler table to a specific trap number where each 
  403.     entry in the table contains a pointer to a function and the number of
  404.     arguments it takes. entNb is the number of entries in the table.
  405.     One thing to note is that svCallConnect()'s trap number is biased by the
  406.     constant TRAP_BASE (cf. cpu.h). That is, if you want to use interrupt 5, 
  407.     you would pass 5 to svCallConnect() and trigger the trap by executing
  408.     the assembly instruction: int $(5 + TRAP_BASE) after first loading 
  409.     %eax with the service you want. On ix86 the assembly file would be 
  410.     something like:
  411.  
  412.     .globl DoSomething
  413.     DoSomething:
  414.     movl $0, %eax    ; index of the call in the table in eax
  415.     int $(TRAP_BASE + trapNb)
  416.     ret
  417.  
  418.     If you have access to CHORUS sources you can look at how the CHORUS 
  419.     libraries are built (i.e. lib/mklib or lib/mkslib).
  420.  
  421.     - svTrapConnect(uint trapNb, KnHdl func) connects a trap handler taking 
  422.     two arguments (thread context and interrupt number) to a the hardware 
  423.     trap trapNb (trapNb is an absolute value in this case). The assembly 
  424.     code to generate the trap would be similar to the code mentioned 
  425.     for svCallConnect for ix86 architectures. On other architectures you can
  426.     either look at how kernel libraries are built if you have access to the
  427.     source code, otherwise look at the processor reference manual or try 
  428.     disassemble a kernel library.
  429.  
  430. 4.2. Supported Microprocessors
  431.      -------------------------
  432.   Various versions of the CHORUS microkernel have been ported to a
  433. variety of microprocessors, either by Chorus Systems or by its 
  434. clients:
  435.  
  436.     - i386/i486/Pentium (various PC/ATs)
  437.     - mc68030/mc68360/mc68040 (MVME147S, QUADS, MVME167S)
  438.     - mc88k
  439.     - SPARC (SPARCstation SLC, SPARCstation Classic, SPARC CPU-3CE)
  440.     - transputer T425/T805/T9000
  441.     - R3000/R4000 (Sony 3410)
  442.     - PA-RISC (HP 9000/834 and 9000/720)
  443.     - YMP (Cray YMP)
  444.  
  445. 4.3. Porting on various platforms
  446.      ----------------------------
  447.     * Chorus on Macintosh?
  448.     The INT (Institut National des Telecommunications, Evry, France) has
  449.     ported the v3 r3 version of the CHORUS microkernel to a Macintosh II CX
  450.     (mc68030-based). CHORUS and MacOS coexist and cooperate on the same
  451.     hardware.
  452.     The paper "Cohabitation and Cooperation of Chorus and MacOS", by
  453.     Christian Bac and Edmond Garnier, was presented at the Usenix Symposium
  454.     on Microkernels and Other Kernel Architectures in Sep 93 in San Diego.
  455.     You can find the paper in the proceedings. It is available from 
  456.     ftp.int-evry.fr:/pub/systeme.
  457.  
  458.     In the same directory you will also find another paper on the same
  459.     subject: "ChorusToolbox : MacOS running on top of Chorus", by Christian
  460.     Bac and Hong Quang Nguyen from INT. This paper was presented at SUUG'94
  461.     in April 94 in Moscow.
  462.  
  463.     * CHORUS on transputers?
  464.     Archipel, Chorus and SGS/Thomson Inmos have ported the CHORUS
  465.     microkernel and the CHORUS/MiX V.3.2 subsystem (SVR3.2 compatible) to
  466.     T425 and T805 transputers. This was done in the context of the Esprit
  467.     project "Harmony" (EC-funded R&D). Initially, a T9000 port was planned to
  468.     be available by now. Due to a delay in the availability of the T9000,
  469.     the CHORUS port (which is underway now), has shifted as well.
  470.       Inmos and Chorus have been working together in order to assure that
  471.     CHORUS/MiX (i.e. UNIX) will run in an optimal manner on the T9000.
  472.  
  473.     * CHORUS on 64-bit architecture?
  474.     CHORUS has been ported to DEC's Alpha, Cray Research's YMP and 
  475.     MIPS' R4000.
  476.  
  477.     * Port of CHORUS on HP-PA?
  478.     On December 1st Jon Inouye <jinouye@cse.ogi.edu> wrote:
  479.  
  480.         Prof. Jonathan Walpole supervised a port of the CHORUS v3.3 
  481.         nucleus to the Hewlett-Packard 9000/834 workstation from late 
  482.         1990 to mid-1991. This was part of a funded research project 
  483.         to evaluate the CHORUS operating system with respect to the 
  484.         Hewlett-Packard PA-RISC architecture. The nucleus did not 
  485.         support any disk/network drivers and performed all console/
  486.         keyboard I/O though IODC (PROM) routines. A CHORUS/MiX V.3.2 
  487.         Process Manager (PM) port was partially completed to the point 
  488.         where UNIX shells and certain system calls were supported ... 
  489.         but not a UNIX file system.
  490.  
  491.         Since then, I have been porting Chorus/MiX V.3.2 (with the v3.4 
  492.         nucleus) to the HP 9000/720. Since I am performing this port in 
  493.         my spare time it is not progressing very fast. The v3.4 nucleus 
  494.         runs along with a serial driver. It lacks other device drivers, 
  495.         FP emulation support (though basic FP operations are supported) 
  496.         and still uses the old HP-UX PDIR structure rather than the more 
  497.         recent HPT. The Ethernet driver is still being debugged as is an 
  498.     ancient version of the MiX V.3.2 PM. The port is being used for 
  499.         virtual memory experiments.
  500.  
  501.         Both ports use a considerable amount (over 40,000 lines combined) 
  502.         of HP-UX source code for the assembly language utilities, boot up, 
  503.         I/O initialization, and device drivers. The 834 port uses a Tut 
  504.         (HP-UX 2.0 modified to run Mach 2.0) base and the 720 port uses 
  505.         a HP-UX 8.0 base. For this reason, we have not been able to release 
  506.         anything because of all the legal implications ... HP, Chorus, USL 
  507.         copyrights.
  508.  
  509.         The evaluation is available as a series of OGI technical reports 
  510.         which can be obtained via anonymous ftp from cse.ogi.edu (129.95.20.2)
  511.         in the directory /pub/tech-reports or via the URL:
  512.         "http://www.cse.ogi.edu/DISC/projects/pa-chorus/pa-chorus.html".
  513.  
  514.     * Are PCI-bus devices supported on ix86?
  515.     PCI devices, like video and IDE, whose I/O mode is compliant with ISA,
  516.     are supported; they are just seen as ISA adapters.
  517.       PCI devices which are not ISA compliant (e.g. the SCSI controller
  518.     and/or the Ethernet controller on some COMPAQs) are not supported;
  519.     supporting them would require modifications in the driver code (and
  520.     possibly also in the CHORUS microkernel code).
  521.  
  522. 4.4. Scheduling and real-time
  523.      ------------------------
  524.     * Scheduling mechanisms and scheduling policies
  525.     The CHORUS microkernel makes a distinction between scheduling mechanism
  526.     and scheduling policies. The core scheduler within the microkernel does
  527.     pure preemptive scheduling (SCHED_FIFO in POSIX RT terms). On top of
  528.     that, different scheduling policies can be implemented in the form of
  529.     scheduling classes; each class communicates with the core scheduler and
  530.     can make its own scheduling decisions within that class based upon
  531.     attributes (priorities, deadlines, etc) and behaviour (time-slicing,
  532.     SCHED_RR, ...).
  533.       Today, 4 scheduling classes are provided: a default class and the 3
  534.     UNIX SVR4 classes (SVR4_TS, SVR4_RT and SVR4_SYS). Work is in progress
  535.     for additional classes (deadline, fair-share, etc) cf the work done 
  536.     by Olivier Gaultier and Olivier Metais at CNAM Paris on the implementation
  537.     of an EDF (Earliest Deadline First) policy in the CHORUS kernel.
  538.  
  539.     * Relative cost of context switch between user and supervisor threads?
  540.     User threads/actors have their own address spaces, and are protected
  541.     from other user address actors.
  542.     Supervisor threads/actors all share the supervisor address space,
  543.     each supervisor actor has its own "slot" in the supervisor address
  544.     space.
  545.  
  546.     For comparison, let's take:
  547.         [U] a context switch between 2 user threads in different user 
  548.             actors,
  549.         [S] a context switch between 2 supervisor threads in different
  550.             supervisor actors
  551.  
  552.     Unlike [U], [S] does not require the saving/restoring of the memory
  553.     context, so [S] is less costly. For the CHORUS/Nucleus v3 r5.2 on 
  554.     a i486/50MHz, the ratio [U]/[S] is 1.57.
  555.  
  556.     * How to measure Interrupt latency?
  557.     The easiest way is to connect an interrupt handler to a hardware timer.
  558.     As soon as the handler is activated, the handler will measure the current
  559.     time and then wake-up a thread, e.g. by doing a V on a semaphore. The
  560.     thread, when returning form its P operation on the same semaphore, will
  561.     also measure the current time. The difference between these 2 time
  562.     measurements is the latency.
  563.  
  564.     If you are using CHORUS/ClassiX or CHORUS/MiX V.4, you should take a
  565.     look at one of the example applications in the tutorial, named ILD
  566.     (Interrupt Latency Demo) which does exactly this work.
  567.  
  568.  
  569. 4.5. CHORUS on Transputers
  570.      ---------------------
  571.     * On transputers, how to communicate from CHORUS to UNIX (SunOS)?
  572.     There is no standard way to do this with CHORUS. This is the kind of 
  573.     things CHORUS/MiX is there for. 
  574.     Specific to transputer, you can use emulated links. On your 
  575.     workstation run a daemon, the "Aserver", which comunicate
  576.     with your b300 box. Together they emulate transputer virtual links 
  577.     over TCP/IP. These links can then be used by transputer and Unix 
  578.     applications to communicate. For details on how to do that, see 
  579.     the sections on the Aserver in the CHORUS documentation (CS/TR-94-82.1
  580.     and CS/TR-94-81.1).
  581.  
  582.     * Use of the INMOS RTL for the C-toolchain to work with sockets?
  583.     [Answer on Dec. 6, 1994 from B. Wipfel <raw@unislc.slc.unisys.com>]:
  584.  
  585.       Guessing that you want to make socket calls from one of your actors,
  586.     and have the B300 handle them in the normal way, the trouble is that
  587.     the transputer implementation of CHORUS uses AServer, not IServer. 
  588.     Since AServer communication is encapsulated in IServer MEGA_PACKETS, 
  589.     the B300 never gets to see any of the socket packets and passes 
  590.     everything to the host. 
  591.  
  592.     A real option is to write a new AServer server to provide your socket 
  593.     service. In this case, all communication will go to the host, and it 
  594.     will make the socket calls on behalf of your actor in the target system. 
  595.     The B300 wouldn't be involved, other than maintaining normal AServer 
  596.     communication with the host. This is kind of a shame, since the B300 
  597.     has the necessary functionality.
  598.  
  599.     A last option might be to use a second root link. Wire up two links 
  600.     from the B300 to your transputer network. Boot the network via one of 
  601.     the links. Configure the second link as a network "EDGE". Have your 
  602.     actor connect to the edge link with one of the AServer routines; 
  603.     something like cmLinkOpen("/dev/raw/00") ? Once the link is open, and 
  604.     you have the channel pointers, it might be possible to attach the 
  605.     socket library channels to these channels. You'll need to do 
  606.     communication via CHORUS' channel I/O routines however. 
  607.  
  608.     * If we have made ourselves a sockgateway process, configured in 
  609.     the .cfs file as:
  610.      ....
  611.     interface(input fromhost, output tohost,
  612.           input formChorus,
  613.           output toChorus);
  614.  
  615.     Where do we connect the input and outputs ?
  616.     [Answer on Nov. 25, 1994 from N. Stephen <stephen@osf.org>]:
  617.  
  618.       I don't know what release you might have, but look up the #device 
  619.     primitive in the build tool users manual. This primitive allows you 
  620.     to attach native transputer processes' channels (which normally 
  621.     control devices) to the CHORUS world, and does all the necessary 
  622.     wiring so that these channels are accessible from the connection 
  623.     manager. There may also be an example of this being done in one 
  624.     of the tutorials, if you have them with your release - the CHORUS 
  625.     Nucleus Tutorial (2), mixing CHORUS and Native transputer code.
  626.  
  627. 4.6. Comparison with other OS
  628.      ------------------------
  629.     * differences between Mach and CHORUS?
  630.     There are a lot of similarities between the concepts of the 
  631.     CHORUS v3 r5 microkernel and the Mach 3.0 microkernel: IPC, threads, 
  632.     memory management. 
  633.  
  634.     Some of the differences are:
  635.  
  636.     ------------------------------------------
  637.     Feature                     Mach    CHORUS
  638.     ------------------------------------------
  639.     Supervisor actors/tasks     no      yes
  640.     Device drivers out of uK    no      yes
  641.     Global object (port) names  no      yes
  642.     Typed messages              yes     no
  643.     Realtime                    no?     yes
  644.     Sender port                 no      yes
  645.     Send-once                   yes     no
  646.     RPC                         no?     yes
  647.     Reliable IPC                yes     no
  648.     Port group (destination)    no      yes
  649.     Scheduling classes          ?       yes
  650.     (Counting) semaphores       no      yes
  651.     Condition variables         yes     no
  652.     Support for non-VM machines no?     yes
  653.     ------------------------------------------
  654.  
  655.     See also the reference [Dean, 92] (cf. section 2.3)
  656.     for more elements of comparison between the two kernels.
  657.  
  658.     (For comparison with other kernels see [Tanenbaum, 1994],
  659.     [Tanenbaum, 1995] in section 2.3)
  660.  
  661.  
  662. 4.7. Performances
  663.      ------------
  664.     * Is there any system for performance analysis?
  665.     As far as the CHORUS microkernel applications ("actors") are 
  666.     concerned, the CHORUS/Profiler and the CHORUS benchmarks can be 
  667.     used.
  668.     The CHORUS/Profiler allows one to obtain and display symbolic
  669.     call-graph profile data for actors (similar to UNIX' gprof(1)):
  670.     callers, calllees, absolute and relative time spent in different
  671.     procedures within one actor. Actors are to be compiled with the 
  672.     -p option.  The profiler consists of a supervisor actor (PROF) 
  673.     plus 2 CHORUS/MiX utilities.  Profiling be can enabled/disabled 
  674.     dynamically using the CHORUS/MiX utility profctl(1).  profctl(1) 
  675.     stores the raw profiling data in a UNIX file, which can then be 
  676.     exploited by the report generator profrpg(1) in order to produce 
  677.     a human-readable profile report. See ftp.chorus.fr:/pub/chorus-
  678.     datasheets/Profiler_v3_r4.{ascii,ps.Z}.
  679.     CHORUS benchmarks allow you to get performance figures for 
  680.     individual microkernel system calls. For some system calls, like 
  681.     ipcSend(K), you get performance figures for different cases/parameters 
  682.     (small/medium/big message sizes). These basic figures can also help 
  683.     you to analyse and tune the performance of your microkernel applications.
  684.  
  685.     In the context of the ESPRIT project Ouverture, Alcatel, Siemens and
  686.     Chorus have designed and implemented so-called hooks for monitoring 
  687.     and debugging in the CHORUS microkernel. These hooks are a clean set 
  688.     of new microkernel system calls which allow monitoring and debugging 
  689.     tools (e.g., PATOC, PARTAMOS) to be informed about the occurrence of 
  690.     events they're interested in (context switch, message arrival, thread
  691.     creation, etc). They will be available in a future CHORUS product
  692.     release.
  693.  
  694.     PATOC is a graphical tool (Motif-based) that allows to monitor 
  695.     applications running on CHORUS. It is event based and is able 
  696.     to display its information is various forms (diagrams, bar-charts 
  697.     etc). PATOC is not a product but rather a working prototype. 
  698.  
  699. 4.8. Object Oriented Issues
  700.      ----------------------
  701.     * How is CHORUS Object-Oriented?
  702.     The major part (>90%) of the CHORUS microkernel is written in C++. 
  703.     OO techniques are used in the implementation of the microkernel, but the
  704.     API exported by the microkernel is a traditional procedure call based
  705.     interface (like UNIX).
  706.  
  707. 5. OS Personalities
  708.    ================
  709. 5.1. OS personalities available on top of CHORUS?
  710.      -------------------------------------------
  711.   Chorus Systems has developed the following personalties:
  712.  
  713.     - SVR4.0
  714.     - SVR3.2
  715.     - SCO ODT 3.0
  716.     - BSD4.3
  717.     - object-oriented (CHORUS/COOL)
  718.     - POSIX real-time (POSIX 1003.1b/.1c, former .4/.4a)
  719.  
  720.   Others have developed, or are developing, personalities for SVR4.2 MP,
  721. UNICOS, MacOS, CHILL, ESTEREL, TINA DPE, and a number of (proprietary) 
  722. real-time OSs.
  723.  
  724. 5.2. CHORUS/MiX V.3.2
  725.      ----------------
  726.  
  727.     * What is the link between a u_thread and a kernel thread?
  728.     A u_thread is an abstraction, created by the CHORUS/MiX V.3.2
  729.     subsystem, on top of the microkernel threads (like a UNIX process 
  730.     is created on top of a CHORUS actor).  Each u_thread is mapped 1-1 
  731.     to a microkernel thread. A u_thread has some UNIX-specific attributes, 
  732.     like signal context, which is managed at the CHORUS/MiX subsystem 
  733.     level, as an added value w.r.t. a microkernel thread.
  734.  
  735.     * Which synchronisation primitives are offered to u_threads?
  736.     Sempahores and mutexes.
  737.  
  738.     * Do u_threads support Thread Specific Data?
  739.     Yes, through the threadsafe C library (c_threadPrivate(3CT),
  740.     c_getPrivate(3CT)). These functions are in fact built on top of the
  741.     software registers described for the kernel threads (cf 4.1).
  742.  
  743.     * How are u_threads scheduled?
  744.     By the microkernel, just like any other thread.
  745.     If one want to implement N user level threads on top of 1 kernel 
  746.     thread, he need a user level scheduler in some kind of run-time 
  747.     library (just like an Ada run-time schedules multiple Ada tasks 
  748.     within one Ada program).
  749.  
  750.     * Is there a way to calculate the size of a u_thread stack?
  751.     For dynamic calculation, the best approach is probably to fill 
  752.     the stack you allocate with a specific pattern, and then at 
  753.     run-time (or at thread termination) control which part of the 
  754.     stack still contains the pattern. This allows to calculate 
  755.     which part of the initial stack has (not) been used.
  756.  
  757.     To detect a stack overflow, the classical approach is to surround 
  758.     the stack by some chunks of memory that are mapped read-only.
  759.  
  760.     * Is it better to put the thread stack in the data segment or in 
  761.     the heap area?
  762.     The only advantage of putting it on the heap is that the corresponding
  763.     memory can be allocated (and freed) dynamically, according to the
  764.     application's run-time behaviour and needs. If you allocate it as 
  765.     data, the corresponding memory is always allocated, even if your 
  766.     thread doesn't exist yet/anymore.
  767.  
  768.     * What are the differences between an u_thread and a c_thread?
  769.     The c_threadXxx(3CT) interface is a library, built upon the 
  770.     u_threadXxx(2C) interface, and is inspired by early drafts of 
  771.     the POSIX pthreads interface (POSIX 1003.4a, later renamed to 
  772.     .1c). It offers a higher level interface than u_threadXxx(2C), 
  773.     e.g.:
  774.  
  775.     - when creating a c_thread the library creates the stack 
  776.       for you, while for a u_thread you have to allocate the 
  777.       stack yourself,
  778.     - there is a routine allowing one c_thread to wait for the 
  779.       termination of another c_thread (c_threadJoin),
  780.     - there are routines to allocate and access per c_thread 
  781.       private global data.
  782.  
  783.  
  784. 5.3. CHORUS/COOL-ORB
  785.      ---------------
  786.  
  787.     * How can I write an CORBA::Any to a file and reading it back
  788.     from file without any knowledge about the type?
  789.  
  790.     Reply from <ciceron@chorus.fr> on July 25th:
  791.     The idea is to fill an area of memory with the any value. The
  792.     memory must be filled in the same way COOL builds its
  793.     communication messages. Once the memory image is built, you
  794.     simply have to write it. On the same idea you can read back
  795.     the any. With this scheme, you don't need to cope with the
  796.     type of the any (and you may also not have it). 
  797.  
  798.  
  799.     I've written a small persistent generic distributed database
  800.     on top of CHORUS/COOL ORB. It uses this technique which works
  801.     very well. (This is not CORBA but... it's cool)
  802.  
  803.     Here is how you could write:
  804.  
  805.     CORBA_Any any = ...
  806.     long size = ::marshalSize(any);
  807.  
  808.     COOL_ComBufDesc buffer(size);
  809.     buffer <<= any;
  810.  
  811.     write(fd, buffer.buffer(), size);
  812.  
  813.     Here is how you could read:
  814.  
  815.     struct stat st;
  816.     fstat(fd, &st);
  817.  
  818.     COOL_ComBufDesc buffer(st.st_size);
  819.     read(fd, buffer.buffer(), st.st_size);
  820.  
  821.     CORBA_Any any;
  822.     buffer >>= any;
  823.  
  824.     * Array/sequences manipulation with CHORUS/COOL.
  825.  
  826.     From <ciceron@chorus.chorus.fr> Mon Sep  2, 1996:
  827.     Here is the solution for COOL ORB. With COOL you can take
  828.     the address of the first element of the array and use it as the
  829.     beginning of the buffer holding the sequence. For example:
  830.  
  831.     // IDL:
  832.     typedef sequence<octet> OctetSeq;
  833.  
  834.     // C++
  835.     OctetSeq* seq = ...;    // Passed to the server implementation 
  836.  
  837.     // CORBA [] operator returns a reference to the first element
  838.     CORBA_Octet& o = (*seq)[0];
  839.  
  840.     // Convert to a pointer and you get the begining of the buffer
  841.     CORBA_Octet* p = &o;
  842.  
  843.     You can then optimize the extraction of your data...
  844.  
  845.     * list of platforms supported for CHORUS/COOL?
  846.  
  847.     For an up to date list you can look at the chorus web site at 
  848.     <http://www.chorus.com/> in the COOL section. The list of 
  849.     platforms supported by CHORUS/COOL r3.1 is the following:
  850.  
  851. +----------------------------------------------------------------+
  852. | System                        | Compiler       | Type          |
  853. |----------------------------------------------------------------|
  854. | AIX 2.3                       | gcc 2.7.2 g++  | mono-threaded |
  855. |----------------------------------------------------------------|
  856. | ClassiX r2.3 for i386at       | Dev System r1.1| multi-threaded|
  857. |----------------------------------------------------------------|
  858. | ClassiX r2.3 for MVME167      | Dev System r3.1| multi-threaded|
  859. |----------------------------------------------------------------|
  860. | ClassiX r3.0 for i386at       | Dev System r4.0| multi-threaded|
  861. |----------------------------------------------------------------|
  862. | Fusion r2                     | SCO C++ 3.1.1  | multi-threaded|
  863. |----------------------------------------------------------------|
  864. | Linux 1.2                     | gcc 2.7.2 g++  | mono-threaded |
  865. |----------------------------------------------------------------|
  866. | SCO OpenDesktop 3.0           | SCO C++ 3.1.1  | mono-threaded |
  867. |                               ---------------------------------|
  868. |                               | gcc 2.7.2 g++  | mono-threaded |
  869. |----------------------------------------------------------------|
  870. | SCO OpenServer 5.0            | SCO C++ 3.1.1  | mono-threaded |
  871. |                               ---------------------------------|
  872. |                               | gcc 2.7.2 g++  | mono-threaded |
  873. |----------------------------------------------------------------|
  874. | Solaris 2.5                   | Sparc C++ V4.1 | mono-threaded |
  875. |                               ---------------------------------|
  876. |                               | Sparc C++ V4.1 | multi-threaded|
  877. |                               ---------------------------------|
  878. |                               | gcc 2.7.2 g++  | mono-threaded |
  879. |----------------------------------------------------------------|
  880. | SunOS 4.1.3                   |Sparc C++ V2.0.1| mono-threaded |
  881. |                               ---------------------------------|
  882. |                               | gcc 2.7.2 g++  | mono-threaded |
  883. |                               ---------------------------------|
  884. |                               |Sparc C++ V4.0.1| mono-threaded |
  885. |----------------------------------------------------------------|
  886. |Windows NT, Windows 95         | Visual C++ 4.0 | mono-threaded |
  887. |                               ---------------------------------|
  888. |                               | Visual C++ 4.0 | multi-threaded|
  889. +----------------------------------------------------------------+
  890.  
  891.     * Implementation of COOL_Mutex and COOL_Sem?
  892.  
  893.     Reply from <ciceron@chorus.fr> on April 7, 1997:
  894.     COOL_Mutex/COOL_Sem are based on the underlying operating system
  895.     primitives. That is: mutexGet/mutexRel/semP/semV on CHORUS/OS,
  896.     mutex_lock/mutex_unlock/sema_wait/sema_post on Solaris 2.5, and others
  897.     on Windows etc...
  898.  
  899.     * How to compile the demo examples of CHORUS/COOL-ORB r4.1 for 
  900.     debugging purposes?
  901.  
  902.     You must use: make CXXDEBUGFLAGS="-g -O"
  903.  
  904.     * We are using Orbix 2.2 on NT 4.0, and want to create many CORBA objects
  905.     per process (at least several thousands to tens of thousands).
  906.     From our tests it seems that the time it takes to allocate such objects
  907.     is in linear relation to the number of objects.
  908.     Has anyone tackled this problem successfully ? Do other ORBs have a 
  909.     more efficient solution to this problem ?
  910.  
  911.     <From ciceron@dimba.chorus.fr Fri Aug 29, 1997>:
  912.     In COOL ORB, the registration depends on the OA that you are using.
  913.     The standard OA proposed by COOL uses a hash table for this. This scales
  914.     quite well. You can imagine to provide a new OA that registers in a binary
  915.     tree (balanced tree would be even better).
  916.  
  917.     To support billions of objects, you should have a look at the Variable 
  918.     Sized Object Reference feature that COOL ORB supports. A single servant 
  919.     can be used by many objects: the object reference always refers to the 
  920.     same servant BUT it also contains additional data which is specific to 
  921.     the object. Have a look at the 'simpleTree' demo which illustrates a 
  922.     binary tree and only one servant for referencing all the nodes. Your 
  923.     tree can contain billions of nodes, you will always have a single servant.
  924.  
  925.     In the next release, COOL ORB will propose a new OA that supports compounds
  926.     of servants. This will allow you to register many servants (any type) in 
  927.     a single registration call to the OA.
  928.  
  929.     Note that beside the performance aspect that you are facing, there is a 
  930.     memory problem too. Each time you register a servant, the OA needs to 
  931.     allocate some memory to record it. If you want to support billions of 
  932.     servants, you must consider this. Having a single servant for implementing
  933.     many objects is a first way to reduce the memory usage. Using the 
  934.     compounds OA is another way.
  935.  
  936.  
  937. 5.4. CHORUS/ClassiX
  938.      ---------------
  939.  
  940.     * I am trying to write an experimental network protocol on top of
  941.     CHORUS/Classix and found that I get Segmentation fault...
  942.  
  943.     <From maze@crf.canon.fr Tue Sep 30, 1997>:
  944.     Wrong Imakefile: the ndm library is missing in the libs part of the 
  945.     ClassiXSupProgramTarget macro.
  946.     As the actor is a relocatable supervisor actor, the ndmGetMajMin routine
  947.     is left undefined in the binary, leading to the segmentation fault.
  948.  
  949.     In you Imakefile you should have:
  950.  
  951.     SRCS = hello.c
  952.  
  953.     LIBS = $(MERGEDIR)/lib/ndmlib/ndmlib.s.a ClassiXSupLibs
  954.     ClassiXSupProgramTarget(hello, hello.o, , $(LIBS), ClassiXReloc)
  955.     DependTarget()
  956.  
  957. 6. Other software
  958.    ================
  959.  
  960.     * We are looking for a ISAM file library or a lightweight database 
  961.     (in terms of storage, runtime overhead and price!) running under CHORUS 
  962.     (or under BSD UNIX 4.2 if the source code is available).
  963.       So far, I found two candidate libraries. The first one is the famous
  964.     C-ISAM; However Informix doesn't sell this product anymore (at least not 
  965.     in Germany). The second one is called CQL++ of Machine Independent 
  966.     Software Corporation, Scottsdale, AZ. Has anyone heard of it or even 
  967.     used it in a software project, respectively?
  968.  
  969.     <From scrantr@ix.netcom.com, Wed Aug 27, 1997>:
  970.     Mix Software (Richardson, Texas) also sells for *cheap* an ISAM
  971.     database library using b+tree indexing.  Source is available,
  972.     and the package includes a nice manual describing the library.
  973.  
  974.     See http://www.mixsoftware.com/product/database.htm
  975.  
  976.