libspe-1.2.2/COPYING0000640000076400007640000006350010533602310013612 0ustar cellbldcellbld GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! libspe-1.2.2/Doxyfile0000640000076400007640000013501410533602310014265 0ustar cellbldcellbld# Doxyfile 1.3.9.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = libspe # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = 1.1 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of source # files, where putting all generated files in the same directory would otherwise # cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, # Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, # Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, # Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, # Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # This tag can be used to specify the encoding used in the generated output. # The encoding is not always determined by the language that is chosen, # but also whether or not the output is meant for Windows or non-Windows users. # In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES # forces the Windows encoding (this is the default for the Windows binary), # whereas setting the tag to NO uses a Unix-style encoding (the default for # all platforms other than Windows). USE_WINDOWS_ENCODING = NO # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is used # as the annotated text. Otherwise, the brief description is used as-is. If left # blank, the following values are used ("$name" is automatically replaced with the # name of the entity): "The $name class" "The $name widget" "The $name file" # "is" "provides" "specifies" "contains" "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited # members of a class in the documentation of that class as if those members were # ordinary class members. Constructors, destructors and assignment operators of # the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like the Qt-style comments (thus requiring an # explicit @brief command for a brief description. JAVADOC_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. # If set to NO, the detailed description appears after the member # documentation. DETAILS_AT_TOP = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources # only. Doxygen will then generate output that is more tailored for Java. # For instance, namespaces will be presented as packages, qualified scopes # will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. SHOW_DIRECTORIES = YES #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp # *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories # that are symbolic links (a Unix filesystem feature) are excluded from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. EXCLUDE_PATTERNS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = YES # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_PREDEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse the # parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or # super classes. Setting the tag to NO turns the diagrams off. Note that this # option is superseded by the HAVE_DOT option below. This is only a fallback. It is # recommended to install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = YES # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = YES # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will # generate a call dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected # functions only using the \callgraph command. CALL_GRAPH = YES # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found on the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_WIDTH = 1024 # The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_HEIGHT = 1024 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes that # lay further from the root node will be omitted. Note that setting this option to # 1 or 2 may greatly reduce the computation time needed for large code bases. Also # note that a graph may be further truncated if the graph's image dimensions are # not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). # If 0 is used for the depth value (the default), the graph is not depth-constrained. MAX_DOT_GRAPH_DEPTH = 0 # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO libspe-1.2.2/Makefile0000640000076400007640000001206510574027771014240 0ustar cellbldcellbld#* #* libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS #* Copyright (C) 2005 IBM Corp. #* #* This library is free software; you can redistribute it and/or modify it #* under the terms of the GNU Lesser General Public License as published by #* the Free Software Foundation; either version 2.1 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 Lesser General Public #* License for more details. #* #* You should have received a copy of the GNU Lesser General Public License #* along with this library; if not, write to the Free Software Foundation, #* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #* X86 = $(shell if [ "`uname -m | grep ppc`" == "" ] ; then echo 1 ; fi) CROSS_COMPILE = $(shell if [ "`cat /proc/cpuinfo | grep Broadband`" == "" ] ; \ then echo 1 ; fi) ifeq "$(X86)" "1" CROSS ?= /opt/cell/toolchain-3.3/bin/ppu- EXTRA_CFLAGS = -m32 -mabi=altivec # RPM defined default flags may not work with this cross-compiler override OPTFLAGS = endif ifeq "$(CROSS_COMPILE)" "1" SYSROOT ?= ../../../sysroot prefix ?= /usr else prefix ?= /usr/local endif exec_prefix = ${prefix} bindir = ${exec_prefix}/bin libdir = ${exec_prefix}/lib includedir = ${prefix}/include speinclude = ${prefix}/spu/include DESTDIR := ROOT := ${DESTDIR}${SYSROOT} INSTALL := /usr/bin/install -c INSTALL_PROGRAM := ${INSTALL} -m 755 INSTALL_DATA := ${INSTALL} -m 644 INSTALL_LINK := ln -sf INSTALL_DIR := ${INSTALL} -d -m 755 MAJOR_VERSION := 1 MINOR_VERSION := 2.2 libspe_SO := libspe.so.${MAJOR_VERSION}.${MINOR_VERSION} libspe_SONAME := libspe.so.${MAJOR_VERSION} CC := ${CROSS}gcc CTAGS := ctags CFLAGS := -O2 -Wall -I. -fPIC -Iinclude -std=gnu99 \ -Wformat -Wdisabled-optimization \ -Wundef -Wshadow -Wcast-align -Wwrite-strings \ -Wmissing-prototypes -Wmissing-declarations \ -Wmissing-noreturn -Wredundant-decls \ -Wnested-externs -Winline -Wformat \ ${EXTRA_CFLAGS} ${OPTFLAGS} ifdef DEBUG CFLAGS += -DDEBUG -g endif libspe_OBJS := elf_loader.o spe.o spethreads.o dma.o ps.o handler.o default_syscall_handler.o default_c99_handler.o default_posix1_handler.o #all: $(libspe_SO) libspe.a elfspe elfspe-register all: $(libspe_SO) libspe.a $(libspe_SO): $(libspe_OBJS) $(CC) $(CFLAGS) -shared -o $@ $^ -lpthread -lrt -Wl,--soname=${libspe_SONAME} libspe.a: $(libspe_OBJS) $(CROSS)ar -r libspe.a *.o elfspe: elfspe.o $(libspe_SO) $(CC) $(CFLAGS) -o $@ $< $(libspe_SO) touch tests/Makefile # # when building in the cross environment this script should reference the # boot-time relative location not the sysroot relative location. # elfspe-register: tools/elfspe-register sed -e "s%@BINDIR@%${bindir}%g" <$< >$@ chmod +x $@ #install: spe.h $(libspe_SO) elfspe elfspe-register libspe.a install: spe.h $(libspe_SO) libspe.a $(INSTALL_DIR) $(ROOT)$(libdir) $(INSTALL_DATA) libspe.a $(ROOT)$(libdir)/libspe.a $(INSTALL_PROGRAM) $(libspe_SO) $(ROOT)$(libdir)/$(libspe_SO) $(INSTALL_LINK) $(libspe_SO) $(ROOT)$(libdir)/$(libspe_SONAME) $(INSTALL_LINK) $(libspe_SONAME) $(ROOT)$(libdir)/libspe.so $(INSTALL_DIR) $(ROOT)$(includedir) $(INSTALL_DATA) libspe.h $(ROOT)$(includedir)/libspe.h $(INSTALL_DATA) cbea_map.h $(ROOT)$(includedir)/cbea_map.h $(INSTALL_DIR) $(ROOT)$(speinclude) $(INSTALL_DATA) cbea_map.h $(ROOT)$(speinclude)/cbea_map.h $(INSTALL_DIR) $(ROOT)$(bindir) # $(INSTALL_PROGRAM) elfspe $(ROOT)$(bindir)/elfspe # $(INSTALL_PROGRAM) elfspe-register $(ROOT)$(bindir)/elfspe-register # $(INSTALL_PROGRAM) elfspe-unregister $(ROOT)$(bindir)/elfspe-unregister tests: tests/Makefile make -C tests tags: $(CTAGS) -R . PACKAGE = libspe FULLNAME = $(PACKAGE)-$(MAJOR_VERSION).$(MINOR_VERSION) TARBALL = $(SOURCES)$(FULLNAME).tar.gz SOURCEFILES = $(TARBALL) #RPMBUILD = ppc32 rpmbuild --target=ppc RPMBUILD = rpmbuild # ../make.rules contains the local rpm build infrastructure in CVS -include ../make.rules rpms: rpm rpm32 rpm32: HOME=$(PWD) $(RPMBUILD) --target=ppc -ba $(SPEC) $(RPMFLAGS) rpm64: HOME=$(PWD) $(RPMBUILD) --target=ppc64 -ba $(SPEC) $(RPMFLAGS) tarball: $(TARBALL) $(TARBALL): $(SOURCES) rm -f $(FULLNAME) ln -s . $(FULLNAME) tar czf $@ --exclude=$(FULLNAME).tar.gz \ --exclude=$(FULLNAME)/$(FULLNAME) \ --exclude=CVS $(FULLNAME)/* doc: text pdf text: xml cd doc; xsltproc extractfunctions.xslt ../xml/all.xml > functions.txt xml: clean doxygen doc/DoxyfileRef cd xml; xsltproc combine.xslt index.xml >all.xml pdf: apiref detail detail: clean doxygen doc/Doxyfile cd latex; make; cp refman.pdf ../doc/detail.pdf apiref: clean doxygen doc/DoxyfileRef cd latex; make; cp refman.pdf ../doc/apiref.pdf clean: rm -f $(libspe_SO) libspe.a $(libspe_OBJS) *~ tags elfspe elfspe-register rm -f elfspe.o $(TARBALL) $(FULLNAME) rm -rf xml rm -rf latex rm -rf html make -C tests clean .PHONY: all clean tests tags libspe-1.2.2/cbea_map.h0000640000076400007640000000457710533602310014470 0ustar cellbldcellbld/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _cbea_map_h_ #define _cbea_map_h_ #ifdef __cplusplus extern "C" { #endif /* spe problem state areas */ typedef struct spe_mssync_area { unsigned int MFC_MSSync; } spe_mssync_area_t; typedef struct spe_mfc_command_area { unsigned char reserved_0_3[4]; unsigned int MFC_LSA; unsigned int MFC_EAH; unsigned int MFC_EAL; unsigned int MFC_Size_Tag; union { unsigned int MFC_ClassID_CMD; unsigned int MFC_CMDStatus; }; unsigned char reserved_18_103[236]; unsigned int MFC_QStatus; unsigned char reserved_108_203[252]; unsigned int Prxy_QueryType; unsigned char reserved_208_21B[20]; unsigned int Prxy_QueryMask; unsigned char reserved_220_22B[12]; unsigned int Prxy_TagStatus; } spe_mfc_command_area_t; typedef struct spe_spu_control_area { unsigned char reserved_0_3[4]; unsigned int SPU_Out_Mbox; unsigned char reserved_8_B[4]; unsigned int SPU_In_Mbox; unsigned char reserved_10_13[4]; unsigned int SPU_Mbox_Stat; unsigned char reserved_18_1B[4]; unsigned int SPU_RunCntl; unsigned char reserved_20_23[4]; unsigned int SPU_Status; unsigned char reserved_28_33[12]; unsigned int SPU_NPC; } spe_spu_control_area_t; typedef struct spe_sig_notify_1_area { unsigned char reserved_0_B[12]; unsigned int SPU_Sig_Notify_1; } spe_sig_notify_1_area_t; typedef struct spe_sig_notify_2_area { unsigned char reserved_0_B[12]; unsigned int SPU_Sig_Notify_2; } spe_sig_notify_2_area_t; #ifdef __cplusplus } #endif #endif libspe-1.2.2/default_c99_handler.c0000640000076400007640000014632610533602310016540 0ustar cellbldcellbld/* default_c99_handler.c - emulate SPE C99 library calls. * * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include "default_c99_handler.h" #include "handler_utils.h" /* SPE C99 Handlers - Overview: * This file implements handlers for SPE C99 library operations such * as printf(3) using standard C library facilities that are available * on the PPE. * * This approach optimizes for space over time. The local store footprint * of the SPE C99 library is reduced by handling file and string operations * on the PPE. This allows the programmer to reserve local store for high * compute intensity software, while still providing functional interfaces. * * The major drawback of this approach is performance. Since I/O is not * buffered on the SPE, application performance may suffer with repeated * calls to putc(3), for instance. Applications requiring high performance * buffered I/O should consider other solutions, such as NEWLIB. * * SPE-side Stubs: * The SPE-side of this interface is most likely implemented with a set of * assembly language stub routines. These are responsible for pushing SPE * register parameters onto the stack per the SPE-ABI, and then for executing * a stop-and-signal instruction with a reserved signal code (currently 0x2100). * By convention, the next word following the stop-and-signal instruction * will contain the C99 op-code along with a pointer to the beginning of * the call stack frame. * * Variable argument library calls are converted side into equivilent va_list * form, i.e. printf(3) becomes vprintf(3) and scanf(3) becomes vscanf(3). This * conversion takes place within the SPE stub routines. * * PPE-Side Handlers: * The PPE application or library receives stop-and-signal notification * from the OS. The default_c99_handler() routine is then called in order * to parse the C99 op-code and branch to a specific C99 handler, such as * default_c99_handler_vprintf(). * * The C99 handlers use direct-mapped access to LS in order to fetch parameters * from the stack frame, and to place return values (including errno) into the * expected locations. * * Known Errata: * 1. The C99 handlers are currently written assuming a 32b PPC-ABI. * A small ammount of work will be necessary to make the vargs * handlers functional in 64b PPC-ABI. */ #define SPE_C99_OP_SHIFT 24 #define SPE_C99_OP_MASK 0xff #define SPE_C99_DATA_MASK 0xffffff #define SPE_C99_OP(_v) (((_v) >> SPE_C99_OP_SHIFT) & SPE_C99_OP_MASK) #define SPE_C99_DATA(_v) ((_v) & SPE_C99_DATA_MASK) enum { SPE_C99_CLEARERR=0x01, SPE_C99_FCLOSE, SPE_C99_FEOF, SPE_C99_FERROR, SPE_C99_FFLUSH, SPE_C99_FGETC, SPE_C99_FGETPOS, SPE_C99_FGETS, SPE_C99_FILENO, SPE_C99_FOPEN, SPE_C99_FPUTC, SPE_C99_FPUTS, SPE_C99_FREAD, SPE_C99_FREOPEN, SPE_C99_FSEEK, SPE_C99_FSETPOS, SPE_C99_FTELL, SPE_C99_FWRITE, SPE_C99_GETC, SPE_C99_GETCHAR, SPE_C99_GETS, SPE_C99_PERROR, SPE_C99_PUTC, SPE_C99_PUTCHAR, SPE_C99_PUTS, SPE_C99_REMOVE, SPE_C99_RENAME, SPE_C99_REWIND, SPE_C99_SETBUF, SPE_C99_SETVBUF, SPE_C99_SYSTEM, SPE_C99_TMPFILE, SPE_C99_TMPNAM, SPE_C99_UNGETC, SPE_C99_VFPRINTF, SPE_C99_VFSCANF, SPE_C99_VPRINTF, SPE_C99_VSCANF, SPE_C99_VSNPRINTF, SPE_C99_VSPRINTF, SPE_C99_VSSCANF, SPE_C99_LAST_OPCODE, }; #define SPE_C99_NR_OPCODES ((SPE_C99_LAST_OPCODE - SPE_C99_CLEARERR) + 1) #define SPE_STDIN 1 #define SPE_STDOUT 2 #define SPE_STDERR 3 #define SPE_FOPEN_MAX (FOPEN_MAX+1) #define SPE_FOPEN_MIN 4 /** * spe_FILE_ptrs - an indexed array of 'FILE *', used by SPE C99 calls. * * A layer of indirection to report back indices rather than 'FILE *', * so as to be type safe w/r/t the 64-bit PPC-ABI. * * The indices {0,1,2,3} are aliases to {NULL,stdin,stdout,stderr}. */ static pthread_mutex_t spe_c99_file_mutex = PTHREAD_MUTEX_INITIALIZER; static int nr_spe_FILE_ptrs = 3; static FILE *spe_FILE_ptrs[SPE_FOPEN_MAX] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; typedef unsigned long long __va_elem; #define CHECK_C99_OPCODE(_op) \ if (SPE_C99_OP(opdata) != SPE_C99_ ## _op) { \ DEBUG_PRINTF("OPCODE (0x%x) mismatch.\n", SPE_C99_OP(opdata)); \ return 1; \ } /* Allocate stack space for vargs array. */ #define __VA_LIST_ALIGN 16UL #define __VA_LIST_ALLOCA(_nr) \ (__va_elem *)(((unsigned long)alloca((_nr+1) * sizeof(__va_elem) + __VA_LIST_ALIGN) \ + __VA_LIST_ALIGN - 1) & ~(__VA_LIST_ALIGN - 1)) #ifdef __powerpc64__ #define __VA_LIST_PUT(_vargs, _type, _a) \ ((_type *) ((unsigned long) _vargs + sizeof(__va_elem) - sizeof(_type)))[0] = (_a); \ _vargs = (__va_elem *)_vargs + 1 #define __VA_TEMP_ALLOCA(_nr) (struct __va_temp *) alloca((_nr+1) * sizeof(struct __va_temp)) #else /* !__powerpc64__ */ #define __OFFSET(_type) (sizeof(_type)-1) #define __MASK(_type) ~(__OFFSET(_type)) /* Align '_vargs' properly for '_type'. */ #define __VA_LIST_ALIGN_TO_TYPE(_vargs, _type) \ (((unsigned long) (_vargs) + __OFFSET(_type)) & __MASK(_type)) /* Put a value into the va_list pointed to by '_vargs'. * TO-DO: update this to support 64b PPC-ABI, if needed. */ #define __VA_LIST_PUT(_vargs, _type, _a) \ _vargs = (__va_elem *) __VA_LIST_ALIGN_TO_TYPE(_vargs, _type); \ ((_type *) _vargs)[0] = (_a); \ _vargs = (__va_elem *)(((_type *) _vargs) + 1) #define __VA_TEMP_ALLOCA(_nr) NULL /* unused */ #endif /* !__powerpc64__ */ #define GET_LS_VARG(_name) { \ memcpy(&(_name), GET_LS_PTR(spe_vlist->next_arg), sizeof(_name)); \ spe_vlist->next_arg += 16; \ if ((spe_vlist->next_arg & LS_ADDR_MASK) == \ (spe_vlist->caller_stack & LS_ADDR_MASK)) { \ spe_vlist->next_arg += 32; \ } \ } /* SPE va_list structure, * per SPU-ABI definition. */ struct spe_va_list { unsigned int next_arg; unsigned int pad0[3]; unsigned int caller_stack; unsigned int pad1[3]; }; #if !defined(__powerpc64__) /* PPC-32 va_list structure. * When nr is greater than 8, * called function takes parms * from 'ptr'. */ struct __ppc32_va_list { unsigned char nr_gpr; unsigned char nr_fpr; unsigned short reserved; void *ptr; }; #endif /* __powerpc64__ */ /* Temporary area to save long value or pointer on ppc64. */ struct __va_temp { long long llval; int *ptr; }; /* TO-DO: update these to support 64b PPC-ABI. */ static int __do_vfprintf(FILE * stream, char *format, __va_elem * vlist) { #if !defined(__powerpc64__) struct __ppc32_va_list ap; ap.nr_gpr = 127; ap.nr_fpr = 127; ap.ptr = (void *) vlist; return vfprintf(stream, format, (void *) &ap); #else return vfprintf(stream, format, (void *) vlist); #endif } static int __do_vsprintf(char *string, char *format, __va_elem * vlist) { #if !defined(__powerpc64__) struct __ppc32_va_list ap; ap.nr_gpr = 127; ap.nr_fpr = 127; ap.ptr = (void *) vlist; return vsprintf(string, format, (void *) &ap); #else return vsprintf(string, format, (void *) vlist); #endif } static int __do_vsnprintf(char *string, size_t size, char *format, __va_elem * vlist) { #if !defined(__powerpc64__) struct __ppc32_va_list ap; ap.nr_gpr = 127; ap.nr_fpr = 127; ap.ptr = (void *) vlist; return vsnprintf(string, size, format, (void *) &ap); #else return vsnprintf(string, size, format, (void *) vlist); #endif } static int __do_vfscanf(FILE * stream, char *format, __va_elem * vlist) { #if !defined(__powerpc64__) struct __ppc32_va_list ap; ap.nr_gpr = 127; ap.nr_fpr = 127; ap.ptr = (void *) vlist; return vfscanf(stream, format, (void *) &ap); #else return vfscanf(stream, format, (void *) vlist); #endif } static int __do_vsscanf(char *string, char *format, __va_elem * vlist) { #if !defined(__powerpc64__) struct __ppc32_va_list ap; ap.nr_gpr = 127; ap.nr_fpr = 127; ap.ptr = (void *) vlist; return vsscanf(string, format, (void *) &ap); #else return vsscanf(string, format, (void *) vlist); #endif } #ifdef __powerpc64__ static void __copy_va_temp(struct __va_temp *vtemps) { while (vtemps->ptr) { *vtemps->ptr = vtemps->llval; vtemps++; } } #else /* !__powerpc64__ */ #define __copy_va_temp(vtemps) /* do nothing */ #endif /* __powerpc64__ */ static inline FILE *get_FILE(int nr) { FILE *ret; pthread_mutex_lock(&spe_c99_file_mutex); if (nr <= 0) { ret = NULL; } else if (nr >= SPE_FOPEN_MAX) { ret = NULL; } else { switch (nr) { case SPE_STDIN: ret = (spe_FILE_ptrs[1]) ? spe_FILE_ptrs[1] : stdin; break; case SPE_STDOUT: ret = (spe_FILE_ptrs[2]) ? spe_FILE_ptrs[2] : stdout; break; case SPE_STDERR: ret = (spe_FILE_ptrs[3]) ? spe_FILE_ptrs[3] : stderr; break; default: ret = spe_FILE_ptrs[nr]; break; } } pthread_mutex_unlock(&spe_c99_file_mutex); return ret; } #define SKIP_PRECISION(p, pr) { \ pr = 0; \ if (*p == '.') { \ switch (*++p) { \ case '0': \ case '1': \ case '2': \ case '3': \ case '4': \ case '5': \ case '6': \ case '7': \ case '8': \ case '9': \ while (*p && isdigit(*p)) p++; \ break; \ case '*': \ GET_LS_VARG(pr); \ __VA_LIST_PUT(vlist, int, pr); \ p++; \ break; \ default: \ break; \ } \ } \ } #define SKIP_FIELD_WIDTH(p, fw, output) { \ fw = 0; \ switch (*p) { \ case '0': \ case '1': \ case '2': \ case '3': \ case '4': \ case '5': \ case '6': \ case '7': \ case '8': \ case '9': \ while (*p && isdigit(*p)) p++; \ break; \ case '*': \ if (output) { \ GET_LS_VARG(fw); \ __VA_LIST_PUT(vlist, int, fw); \ } \ p++; \ break; \ default: \ break; \ } \ } #define SKIP_PRINTF_FLAG_CHARS(p) { \ int done = 0; \ do { \ switch (*p) { \ case '#': \ case '0': \ case '-': \ case '+': \ case ' ': \ p++; \ break; \ default: \ done = 1; \ break; \ } \ } while (!done); \ } #define COUNT_FIELD_WIDTH(p, output) { \ switch (*p) { \ case '0': \ case '1': \ case '2': \ case '3': \ case '4': \ case '5': \ case '6': \ case '7': \ case '8': \ case '9': \ while (*p && isdigit(*p)) p++; \ break; \ case '*': \ p++; \ if (output) nr++; \ break; \ default: \ break; \ } \ } #define COUNT_PRECISION(p, output) { \ if (*p == '.') { \ switch (*++p) { \ case '0': \ case '1': \ case '2': \ case '3': \ case '4': \ case '5': \ case '6': \ case '7': \ case '8': \ case '9': \ while (*p && isdigit(*p)) p++; \ break; \ case '*': \ if (output) nr++; \ p++; \ break; \ default: \ break; \ } \ } \ } #define SKIP_SCANF_FLAG_CHARS(p, h, l, sp) { \ int done = 0; \ h = 0; l = 0; sp = 0; \ do { \ switch (*p) { \ case 'h': \ h = 1; \ p++; \ case 'l': \ l++; \ p++; \ break; \ case '*': \ sp = 1; \ p++; \ default: \ done = 1; \ break; \ } \ } while (!done); \ } #define SKIP_CHAR_SET(p) \ { \ char _prev; \ do { \ p = strchr(p, ']'); \ if (p == NULL) { \ DEBUG_PRINTF("SKIP_CHAR_SET() error."); \ return 1; \ } \ _prev = *((p)-1); \ } while ((_prev == '[') || (_prev == '^')); \ } static int __nr_format_args(const char *format) { char *p; int nr = 0; for (p = (char *) format; *p; p++, nr++) { p = strchr(p, '%'); if (!p) { /* Done with formatting. */ break; } } /* Loosely estimate of the number of format arguments * by scanning for '%'. Multiply the return value by * 3 in order to account for variable format width or * precision. */ return nr * 3; } static int __parse_printf_format(char *ls, char *format, struct spe_va_list *spe_vlist, __va_elem * vlist, int nr_vargs) { int fw, pr; int ival; double dval; long long llval; unsigned int ls_offset; char *p; char *str; if (nr_vargs == 0) return 0; for (p = (char *) format; *p; p++) { p = strchr(p, '%'); if (!p) { /* Done with formatting. */ break; } p++; SKIP_PRINTF_FLAG_CHARS(p); SKIP_FIELD_WIDTH(p, fw, 1); SKIP_PRECISION(p, pr); switch (*p) { case 'c': case 'd': case 'i': GET_LS_VARG(ival); __VA_LIST_PUT(vlist, int, ival); break; case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': GET_LS_VARG(dval); __VA_LIST_PUT(vlist, double, dval); break; case 'h': GET_LS_VARG(ival); __VA_LIST_PUT(vlist, int, ival); if (p[1] == 'h') { p += 2; } else { p += 1; } break; case 'l': if (p[1] == 'l') { GET_LS_VARG(llval); __VA_LIST_PUT(vlist, long long, llval); p += 2; } else if (p[1] == 'f' || p[1] == 'F' || p[1] == 'e' || p[1] == 'E' || p[1] == 'g' || p[1] == 'G' ) { GET_LS_VARG(dval); __VA_LIST_PUT(vlist, double, dval); p += 2; } else { GET_LS_VARG(ival); #ifdef __powerpc64__ if (p[1] == 'd') { __VA_LIST_PUT(vlist, long, (long)ival); } else { __VA_LIST_PUT(vlist, unsigned long, (unsigned long)(unsigned int)ival); } #else /* !__powerpc64__*/ __VA_LIST_PUT(vlist, int, ival); #endif /* __powerpc64__*/ p += 1; } break; case 'p': #ifdef __powerpc64__ GET_LS_VARG(ival); __VA_LIST_PUT(vlist, unsigned long, (unsigned long)(unsigned int)ival); break; #endif /* __powerpc64__ */ case 'o': case 'u': case 'x': case 'X': GET_LS_VARG(ival); __VA_LIST_PUT(vlist, int, ival); break; case 's': GET_LS_VARG(ls_offset); str = GET_LS_PTR(ls_offset); __VA_LIST_PUT(vlist, char *, str); break; default: break; } } return 0; } static int __parse_scanf_format(char *ls, char *format, struct spe_va_list *spe_vlist, __va_elem * vlist, struct __va_temp *vtemps, int nr_vargs) { int fw; int format_half, format_long, suppress; unsigned int ls_offset; char *p, *pstart; void *ptr; if (nr_vargs == 0) { #ifdef __powerpc64__ vtemps->ptr = NULL; #endif /* __powerpc64__ */ return 0; } for (p = (char *) format, pstart = (char *) format; *p;) { p = strchr(p, '%'); if (!p) { /* No more formatting. */ break; } p++; SKIP_FIELD_WIDTH(p, fw, 0); SKIP_SCANF_FLAG_CHARS(p, format_half, format_long, suppress); switch (*p) { case 'd': case 'i': case 'o': case 'u': case 'x': if (format_half) { if (!suppress) { GET_LS_VARG(ls_offset); ptr = GET_LS_PTR(ls_offset); __VA_LIST_PUT(vlist, short *, ptr); } } else if (format_long == 2) { if (!suppress) { GET_LS_VARG(ls_offset); ptr = GET_LS_PTR(ls_offset); __VA_LIST_PUT(vlist, long long *, ptr); } #ifdef __powerpc64__ } else if (format_long) { if (!suppress) { GET_LS_VARG(ls_offset); ptr = GET_LS_PTR(ls_offset); vtemps->ptr = ptr; __VA_LIST_PUT(vlist, long long *, &vtemps->llval); vtemps++; } #endif /* __powerpc64__ */ } else { if (!suppress) { GET_LS_VARG(ls_offset); ptr = GET_LS_PTR(ls_offset); __VA_LIST_PUT(vlist, int *, ptr); } } break; case 'e': case 'f': case 'g': if (format_long) { if (!suppress) { GET_LS_VARG(ls_offset); ptr = GET_LS_PTR(ls_offset); __VA_LIST_PUT(vlist, double *, ptr); } } else { if (!suppress) { GET_LS_VARG(ls_offset); ptr = GET_LS_PTR(ls_offset); __VA_LIST_PUT(vlist, float *, ptr); } } break; case 'n': if (!suppress) { GET_LS_VARG(ls_offset); ptr = GET_LS_PTR(ls_offset); __VA_LIST_PUT(vlist, int *, ptr); } break; case 'p': if (!suppress) { GET_LS_VARG(ls_offset); ptr = GET_LS_PTR(ls_offset); #ifdef __powerpc64__ vtemps->ptr = ptr; __VA_LIST_PUT(vlist, long long *, &vtemps->llval); vtemps++; #else /* !__powerpc64__ */ __VA_LIST_PUT(vlist, unsigned long *, ptr); #endif /* !__powerpc64__ */ } break; case 'c': if (!suppress) { GET_LS_VARG(ls_offset); ptr = GET_LS_PTR(ls_offset); __VA_LIST_PUT(vlist, char *, ptr); } break; case 's': if (!suppress) { GET_LS_VARG(ls_offset); ptr = GET_LS_PTR(ls_offset); __VA_LIST_PUT(vlist, char *, ptr); } break; case '[': SKIP_CHAR_SET(p); if (!suppress) { GET_LS_VARG(ls_offset); ptr = GET_LS_PTR(ls_offset); __VA_LIST_PUT(vlist, char *, ptr); } break; case '%': break; default: break; } } #ifdef __powerpc64__ vtemps->ptr = NULL; #endif /* __powerpc64__ */ return 0; } /** * default_c99_handler_remove * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int remove(const char *pathname); */ int default_c99_handler_remove(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); char *path; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(REMOVE); path = GET_LS_PTR(arg0->slot[0]); rc = remove(path); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_rename * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int rename(const char *oldname, const char *newname); */ int default_c99_handler_rename(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); char *oldname; char *newname; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(RENAME); oldname = GET_LS_PTR(arg0->slot[0]); newname = GET_LS_PTR(arg1->slot[0]); rc = rename(oldname, newname); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_tmpfile * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * FILE *tmpfile(void); */ int default_c99_handler_tmpfile(char *ls, unsigned long opdata) { DECL_0_ARGS(); DECL_RET(); int i; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(TMPFILE); if (nr_spe_FILE_ptrs >= SPE_FOPEN_MAX) { PUT_LS_RC(0, 0, 0, EMFILE); } else { for (i = SPE_FOPEN_MIN; i < SPE_FOPEN_MAX; i++) { if (spe_FILE_ptrs[i] == NULL) { spe_FILE_ptrs[i] = tmpfile(); if (spe_FILE_ptrs[i]) nr_spe_FILE_ptrs++; PUT_LS_RC(i, 0, 0, errno); break; } } if (i == SPE_FOPEN_MAX) { PUT_LS_RC(0, 0, 0, EMFILE); } } return 0; } /** * default_c99_handler_tmpnam * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * char *tmpnam(char *s); * * For integrity reasons, we should expose * mkstemp() instead. */ int default_c99_handler_tmpnam(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); char * s; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(TMPNAM); s = GET_LS_PTR(arg0->slot[0]); tmpnam(s); PUT_LS_RC(s, 0, 0, 0); return 0; } /** * default_c99_handler_fclose * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int fclose(FILE *stream); */ int default_c99_handler_fclose(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); FILE *stream; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(FCLOSE); stream = get_FILE(arg0->slot[0]); pthread_mutex_lock(&spe_c99_file_mutex); rc = fclose(stream); if (rc == 0) { spe_FILE_ptrs[arg0->slot[0]] = NULL; nr_spe_FILE_ptrs--; } pthread_mutex_unlock(&spe_c99_file_mutex); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_fflush * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int fflush(FILE *stream); */ int default_c99_handler_fflush(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); FILE *stream; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(FFLUSH); stream = get_FILE(arg0->slot[0]); rc = fflush(stream); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_fopen * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * FILE *fopen(const char *path, const char *mode); */ int default_c99_handler_fopen(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); char *path; char *mode; FILE *f; int i, rc = 0, err = EMFILE; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(FOPEN); path = GET_LS_PTR(arg0->slot[0]); mode = GET_LS_PTR(arg1->slot[0]); pthread_mutex_lock(&spe_c99_file_mutex); if (nr_spe_FILE_ptrs < SPE_FOPEN_MAX) { for (i = SPE_FOPEN_MIN; i < SPE_FOPEN_MAX; i++) { if (spe_FILE_ptrs[i] == NULL) { f = fopen(path, mode); err = errno; if (f) { spe_FILE_ptrs[i] = f; nr_spe_FILE_ptrs++; rc = i; } break; } } } pthread_mutex_unlock(&spe_c99_file_mutex); PUT_LS_RC(rc, 0, 0, err); return 0; } /** * default_c99_handler_freopen * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * FILE *freopen(const char *path, const char *mode, FILE *stream); */ int default_c99_handler_freopen(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); char *path; char *mode; int i; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(FREOPEN); i = arg2->slot[0]; if ((i <= 0) || (i >= SPE_FOPEN_MAX)) { PUT_LS_RC(1, 0, 0, EBADF); } else { path = GET_LS_PTR(arg0->slot[0]); mode = GET_LS_PTR(arg1->slot[0]); pthread_mutex_lock(&spe_c99_file_mutex); spe_FILE_ptrs[i] = freopen(path, mode, get_FILE(i)); if (spe_FILE_ptrs[i]) { PUT_LS_RC(i, 0, 0, 0); } else { PUT_LS_RC(0, 0, 0, errno); } pthread_mutex_unlock(&spe_c99_file_mutex); } return 0; } /** * default_c99_handler_setbuf * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * void setbuf(FILE *stream, char *buf); */ int default_c99_handler_setbuf(char *ls, unsigned long opdata) { DECL_2_ARGS(); FILE *stream; char *buf; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(SETBUF); stream = get_FILE(arg0->slot[0]); buf = GET_LS_PTR(arg1->slot[0]); setbuf(stream, buf); return 0; } /** * default_c99_handler_setvbuf * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int setvbuf(FILE *stream, char *buf, int mode , size_t size); */ int default_c99_handler_setvbuf(char *ls, unsigned long opdata) { DECL_4_ARGS(); DECL_RET(); FILE *stream; char *buf; int mode; size_t size; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(SETVBUF); stream = get_FILE(arg0->slot[0]); buf = GET_LS_PTR(arg1->slot[0]); mode = arg2->slot[0]; size = arg3->slot[0]; rc = setvbuf(stream, buf, mode, size); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_vfprintf * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int vfprintf(FILE *stream, const char *format, va_list ap); */ int default_c99_handler_vfprintf(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); FILE *stream; char *format; int rc, nr_vargs; struct spe_va_list spe_vlist; __va_elem *vlist; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(VFPRINTF); stream = get_FILE(arg0->slot[0]); format = GET_LS_PTR(arg1->slot[0]); memcpy(&spe_vlist, arg2, sizeof(struct spe_va_list)); nr_vargs = __nr_format_args(format); vlist = __VA_LIST_ALLOCA(nr_vargs); rc = __parse_printf_format(ls, format, &spe_vlist, vlist, nr_vargs); rc = (rc == 0) ? __do_vfprintf(stream, format, vlist) : -1; PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_vfscanf * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int vfscanf(FILE *stream, const char *format, va_list ap); */ int default_c99_handler_vfscanf(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); FILE *stream; char *format; int rc, nr_vargs; struct spe_va_list spe_vlist; __va_elem *vlist; struct __va_temp *vtemps; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(VFSCANF); stream = get_FILE(arg0->slot[0]); format = GET_LS_PTR(arg1->slot[0]); memcpy(&spe_vlist, arg2, sizeof(struct spe_va_list)); nr_vargs = __nr_format_args(format); vlist = __VA_LIST_ALLOCA(nr_vargs); vtemps = __VA_TEMP_ALLOCA(nr_vargs); rc = __parse_scanf_format(ls, format, &spe_vlist, vlist, vtemps, nr_vargs); if (rc == 0) { rc = __do_vfscanf(stream, format, vlist); __copy_va_temp(vtemps); } else { rc = EOF; } PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_vprintf * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int vprintf(const char *format, va_list ap); */ int default_c99_handler_vprintf(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); FILE *stream; char *format; int rc, nr_vargs; struct spe_va_list spe_vlist; __va_elem *vlist; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(VPRINTF); stream = get_FILE(SPE_STDOUT); format = GET_LS_PTR(arg0->slot[0]); memcpy(&spe_vlist, arg1, sizeof(struct spe_va_list)); nr_vargs = __nr_format_args(format); vlist = __VA_LIST_ALLOCA(nr_vargs); rc = __parse_printf_format(ls, format, &spe_vlist, vlist, nr_vargs); rc = (rc == 0) ? __do_vfprintf(stream, format, vlist) : -1; PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_vscanf * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int vscanf(const char *format, va_list ap); */ int default_c99_handler_vscanf(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); FILE *stream; char *format; int rc, nr_vargs; struct spe_va_list spe_vlist; __va_elem *vlist; struct __va_temp *vtemps; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(VSCANF); stream = get_FILE(SPE_STDIN); format = GET_LS_PTR(arg0->slot[0]); memcpy(&spe_vlist, arg1, sizeof(struct spe_va_list)); nr_vargs = __nr_format_args(format); vlist = __VA_LIST_ALLOCA(nr_vargs); vtemps = __VA_TEMP_ALLOCA(nr_vargs); rc = __parse_scanf_format(ls, format, &spe_vlist, vlist, vtemps, nr_vargs); if (rc == 0) { rc = __do_vfscanf(stream, format, vlist); __copy_va_temp(vtemps); } else { rc = EOF; } PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_vsnprintf * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int vsnprintf(char *str, size_t size, const char *format, va_list ap); */ int default_c99_handler_vsnprintf(char *ls, unsigned long opdata) { DECL_4_ARGS(); DECL_RET(); char *str; char *format; size_t size; int rc, nr_vargs; struct spe_va_list spe_vlist; __va_elem *vlist; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(VSNPRINTF); str = GET_LS_PTR(arg0->slot[0]); size = arg1->slot[0]; format = GET_LS_PTR(arg2->slot[0]); memcpy(&spe_vlist, arg3, sizeof(struct spe_va_list)); nr_vargs = __nr_format_args(format); vlist = __VA_LIST_ALLOCA(nr_vargs); rc = __parse_printf_format(ls, format, &spe_vlist, vlist, nr_vargs); rc = (rc == 0) ? __do_vsnprintf(str, size, format, (void *) vlist) : -1; PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_vsprintf * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int vsprintf(char *str, const char *format, va_list ap); */ int default_c99_handler_vsprintf(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); char *str; char *format; int rc, nr_vargs; struct spe_va_list spe_vlist; __va_elem *vlist; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(VSPRINTF); str = GET_LS_PTR(arg0->slot[0]); format = GET_LS_PTR(arg1->slot[0]); memcpy(&spe_vlist, arg2, sizeof(struct spe_va_list)); nr_vargs = __nr_format_args(format); vlist = __VA_LIST_ALLOCA(nr_vargs); rc = __parse_printf_format(ls, format, &spe_vlist, vlist, nr_vargs); rc = (rc == 0) ? __do_vsprintf(str, format, vlist) : -1; PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_vsscanf * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int vsscanf(const char *str, const char *format, va_list ap); */ int default_c99_handler_vsscanf(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); char *str; char *format; int rc, nr_vargs; struct spe_va_list spe_vlist; __va_elem *vlist; struct __va_temp *vtemps; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(VSSCANF); str = GET_LS_PTR(arg0->slot[0]); format = GET_LS_PTR(arg1->slot[0]); memcpy(&spe_vlist, arg2, sizeof(struct spe_va_list)); nr_vargs = __nr_format_args(format); vlist = __VA_LIST_ALLOCA(nr_vargs); vtemps = __VA_TEMP_ALLOCA(nr_vargs); rc = __parse_scanf_format(ls, format, &spe_vlist, vlist, vtemps, nr_vargs); if (rc == 0) { rc = __do_vsscanf(str, format, vlist); __copy_va_temp(vtemps); } else { rc = EOF; } PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_fgetc * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int fgetc(FILE *stream); */ int default_c99_handler_fgetc(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); FILE *stream; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(FGETC); stream = get_FILE(arg0->slot[0]); rc = fgetc(stream); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_fgets * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * char *fgets(char *s, int size, FILE *stream); */ int default_c99_handler_fgets(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); char *s; FILE *stream; int size; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(FGETS); s = GET_LS_PTR(arg0->slot[0]); size = arg1->slot[0]; stream = get_FILE(arg2->slot[0]); rc = (fgets(s, size, stream) == s) ? arg0->slot[0] : 0; PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_fileno * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE library operation, implementing: * * int fileno(FILE *stream); */ int default_c99_handler_fileno(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); FILE *stream; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(FILENO); stream = get_FILE(arg0->slot[0]); rc = fileno(stream); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_fputc * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int fputc(int c, FILE *stream); */ int default_c99_handler_fputc(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); FILE *stream; int c; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(FPUTC); c = arg0->slot[0]; stream = get_FILE(arg1->slot[0]); rc = fputc(c, stream); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_fputs * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int fputs(const char *s, FILE *stream); */ int default_c99_handler_fputs(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); char *s; FILE *stream; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(FPUTS); s = GET_LS_PTR(arg0->slot[0]); stream = get_FILE(arg1->slot[0]); rc = fputs(s, stream); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_getc * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int getc(FILE *stream); */ int default_c99_handler_getc(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); FILE *stream; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(GETC); stream = get_FILE(arg0->slot[0]); rc = getc(stream); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_getchar * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int getchar(void); */ int default_c99_handler_getchar(char *ls, unsigned long opdata) { DECL_0_ARGS(); DECL_RET(); FILE *stream; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(GETCHAR); stream = get_FILE(SPE_STDIN); rc = getc(stream); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_gets * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * char *gets(char *s); * * Implementation note: gets() is a classic security/integrity * hole, since its impossible to tell how many characters will * be input. */ int default_c99_handler_gets(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); FILE *stream; char *s, *r; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(GETS); stream = get_FILE(SPE_STDIN); s = GET_LS_PTR(arg0->slot[0]); r = fgets(s, LS_SIZE - arg0->slot[0], stream); rc = (r == s) ? arg0->slot[0] : 0; PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_putc * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int putc(int c, FILE *stream); */ int default_c99_handler_putc(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); FILE *f; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(PUTC); f = get_FILE(arg1->slot[0]); rc = putc(arg0->slot[0], f); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_putchar * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int putchar(int c); */ int default_c99_handler_putchar(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); FILE *stream; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(PUTCHAR); stream = get_FILE(SPE_STDOUT); rc = putc(arg0->slot[0], stream); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_puts * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int puts(const char *s); */ int default_c99_handler_puts(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); char *s; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(PUTS); s = GET_LS_PTR(arg0->slot[0]); rc = puts(s); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_ungetc * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int ungetc(int c, FILE *stream); */ int default_c99_handler_ungetc(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); FILE *stream; int rc, c; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(UNGETC); c = arg0->slot[0]; stream = get_FILE(arg1->slot[0]); rc = ungetc(c, stream); PUT_LS_RC(rc, 0, 0, 0); return 0; } /** * default_c99_handler_fread * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); */ int default_c99_handler_fread(char *ls, unsigned long opdata) { DECL_4_ARGS(); DECL_RET(); void *ptr; size_t size, nmemb; FILE *stream; int rc = 0; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(FREAD); ptr = GET_LS_PTR(arg0->slot[0]); size = arg1->slot[0]; nmemb = arg2->slot[0]; stream = get_FILE(arg3->slot[0]); rc = fread(ptr, size, nmemb, stream); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_fwrite * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); */ int default_c99_handler_fwrite(char *ls, unsigned long opdata) { DECL_4_ARGS(); DECL_RET(); void *ptr; size_t size, nmemb; FILE *stream; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(FWRITE); ptr = GET_LS_PTR(arg0->slot[0]); size = arg1->slot[0]; nmemb = arg2->slot[0]; stream = get_FILE(arg3->slot[0]); rc = fwrite(ptr, size, nmemb, stream); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_fgetpos * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int fgetpos(FILE *stream, fpos_t *pos); */ int default_c99_handler_fgetpos(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); FILE *stream; fpos_t *pos; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(FGETPOS); stream = get_FILE(arg0->slot[0]); pos = (fpos_t *) GET_LS_PTR(arg1->slot[0]); rc = fgetpos(stream, pos); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_fseek * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int fseek(FILE *stream, long offset, int whence); */ int default_c99_handler_fseek(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); FILE *stream; long offset; int whence; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(FSEEK); stream = get_FILE(arg0->slot[0]); offset = (long) arg1->slot[0]; whence = arg2->slot[0]; rc = fseek(stream, offset, whence); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_fsetpos * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int fsetpos(FILE *stream, fpos_t *pos); */ int default_c99_handler_fsetpos(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); FILE *stream; fpos_t *pos; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(FSETPOS); stream = get_FILE(arg0->slot[0]); pos = (fpos_t *) GET_LS_PTR(arg1->slot[0]); rc = fsetpos(stream, pos); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_ftell * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * long ftell(FILE *stream); */ int default_c99_handler_ftell(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); FILE *stream; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(FTELL); stream = get_FILE(arg0->slot[0]); rc = ftell(stream); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_rewind * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * void rewind(FILE *stream); */ int default_c99_handler_rewind(char *ls, unsigned long opdata) { DECL_1_ARGS(); FILE *stream; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(REWIND); stream = get_FILE(arg0->slot[0]); rewind(stream); return 0; } /** * default_c99_handler_clearerr * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * void clearerr(FILE *stream); */ int default_c99_handler_clearerr(char *ls, unsigned long opdata) { DECL_1_ARGS(); FILE *stream; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(CLEARERR); stream = get_FILE(arg0->slot[0]); clearerr(stream); return 0; } /** * default_c99_handler_feof * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int feof(FILE *stream); */ int default_c99_handler_feof(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); FILE *stream; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(FEOF); stream = get_FILE(arg0->slot[0]); rc = feof(stream); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_c99_handler_ferror * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * void ferror(FILE *stream); */ int default_c99_handler_ferror(char *ls, unsigned long opdata) { DECL_1_ARGS(); FILE *stream; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(FERROR); stream = get_FILE(arg0->slot[0]); ferror(stream); return 0; } /** * default_c99_handler_perror * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * void perror(const char *s); */ int default_c99_handler_perror(char *ls, unsigned long opdata) { DECL_1_ARGS(); char *s; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(PERROR); s = GET_LS_PTR(arg0->slot[0]); perror(s); return 0; } /** * default_c99_handler_system * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * SPE C99 library operation, per: ISO/IEC C Standard 9899:1999, * implementing: * * int system(const char *string); */ int default_c99_handler_system(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); char *string; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_C99_OPCODE(SYSTEM); string = GET_LS_PTR(arg0->slot[0]); rc = system(string); PUT_LS_RC(rc, 0, 0, errno); return 0; } int (*default_c99_funcs[SPE_C99_NR_OPCODES]) (char *, unsigned long) = { default_c99_handler_clearerr, default_c99_handler_fclose, default_c99_handler_feof, default_c99_handler_ferror, default_c99_handler_fflush, default_c99_handler_fgetc, default_c99_handler_fgetpos, default_c99_handler_fgets, default_c99_handler_fileno, default_c99_handler_fopen, default_c99_handler_fputc, default_c99_handler_fputs, default_c99_handler_fread, default_c99_handler_freopen, default_c99_handler_fseek, default_c99_handler_fsetpos, default_c99_handler_ftell, default_c99_handler_fwrite, default_c99_handler_getchar, default_c99_handler_getc, default_c99_handler_gets, default_c99_handler_perror, default_c99_handler_putc, default_c99_handler_putchar, default_c99_handler_puts, default_c99_handler_remove, default_c99_handler_rename, default_c99_handler_rewind, default_c99_handler_setbuf, default_c99_handler_setvbuf, default_c99_handler_system, default_c99_handler_tmpfile, default_c99_handler_tmpnam, default_c99_handler_ungetc, default_c99_handler_vfprintf, default_c99_handler_vfscanf, default_c99_handler_vprintf, default_c99_handler_vscanf, default_c99_handler_vsnprintf, default_c99_handler_vsprintf, default_c99_handler_vsscanf, }; /** * default_c99_handler * @ls: base pointer to SPE local-store area. * @opdata: per C99 call opcode & data. * * Top-level dispatch for SPE C99 library operations. */ int default_c99_handler(unsigned long *base, unsigned long offset) { int op, opdata; if (!base) { DEBUG_PRINTF("%s: mmap LS required.\n", __func__); return 1; } offset = (offset & LS_ADDR_MASK) & ~0x1; opdata = *((int *)((char *) base + offset)); op = SPE_C99_OP(opdata); if ((op <= 0) || (op >= SPE_C99_NR_OPCODES)) { DEBUG_PRINTF("%s: Unhandled type %08x\n", __func__, SPE_C99_OP(opdata)); return 1; } default_c99_funcs[op-1] ((char *) base, opdata); return 0; } libspe-1.2.2/default_c99_handler.h0000640000076400007640000000756410533602310016545 0ustar cellbldcellbld/* default_c99_handler.h - emulate SPE C99 library calls. * * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __DEFAULT_C99_HANDLER_H__ #define __DEFAULT_C99_HANDLER_H__ #define SPE_C99_CLASS 0x2100 extern int default_c99_handler(unsigned long *base, unsigned long args); extern int default_c99_handler_clearerr(char *ls, unsigned long args); extern int default_c99_handler_fclose(char *ls, unsigned long args); extern int default_c99_handler_feof(char *ls, unsigned long args); extern int default_c99_handler_ferror(char *ls, unsigned long args); extern int default_c99_handler_fflush(char *ls, unsigned long args); extern int default_c99_handler_fgetc(char *ls, unsigned long args); extern int default_c99_handler_fgetpos(char *ls, unsigned long args); extern int default_c99_handler_fgets(char *ls, unsigned long args); extern int default_c99_handler_fileno(char *ls, unsigned long args); extern int default_c99_handler_fopen(char *ls, unsigned long args); extern int default_c99_handler_fputc(char *ls, unsigned long args); extern int default_c99_handler_fputs(char *ls, unsigned long args); extern int default_c99_handler_fread(char *ls, unsigned long args); extern int default_c99_handler_freopen(char *ls, unsigned long args); extern int default_c99_handler_fseek(char *ls, unsigned long args); extern int default_c99_handler_fsetpos(char *ls, unsigned long args); extern int default_c99_handler_ftell(char *ls, unsigned long args); extern int default_c99_handler_fwrite(char *ls, unsigned long args); extern int default_c99_handler_getc(char *ls, unsigned long args); extern int default_c99_handler_getchar(char *ls, unsigned long args); extern int default_c99_handler_getenv(char *ls, unsigned long args); extern int default_c99_handler_gets(char *ls, unsigned long args); extern int default_c99_handler_perror(char *ls, unsigned long args); extern int default_c99_handler_putc(char *ls, unsigned long args); extern int default_c99_handler_putchar(char *ls, unsigned long args); extern int default_c99_handler_puts(char *ls, unsigned long args); extern int default_c99_handler_remove(char *ls, unsigned long args); extern int default_c99_handler_rename(char *ls, unsigned long args); extern int default_c99_handler_rewind(char *ls, unsigned long args); extern int default_c99_handler_setbuf(char *ls, unsigned long args); extern int default_c99_handler_setvbuf(char *ls, unsigned long args); extern int default_c99_handler_system(char *ls, unsigned long args); extern int default_c99_handler_tmpfile(char *ls, unsigned long args); extern int default_c99_handler_tmpnam(char *ls, unsigned long args); extern int default_c99_handler_ungetc(char *ls, unsigned long args); extern int default_c99_handler_vfprintf(char *ls, unsigned long args); extern int default_c99_handler_vfscanf(char *ls, unsigned long args); extern int default_c99_handler_vprintf(char *ls, unsigned long args); extern int default_c99_handler_vscanf(char *ls, unsigned long args); extern int default_c99_handler_vsnprintf(char *ls, unsigned long args); extern int default_c99_handler_vsprintf(char *ls, unsigned long args); extern int default_c99_handler_vsscanf(char *ls, unsigned long args); #endif /* __DEFAULT_C99_HANDLER_H__ */ libspe-1.2.2/default_posix1_handler.c0000640000076400007640000010107510533602311017350 0ustar cellbldcellbld/* default_posix1_handler.c - emulate SPE POSIX.1 library calls. * * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "default_posix1_handler.h" #include "handler_utils.h" /* SPE POSIX.1 Handlers - Overview: * This file implements handlers for SPE POSIX.1 library calls such as * open(2), using C library facilities available on PPE. * * The main contribution of this layer is to provide the SPE programer * with a set of utilities that operate on a large effective address * space, rather than LS objects. For instance this feature can be * used to to mmap(2) a data file into an address space and then * multi-buffer data into LS in order to avoid staging via expensive * buffered-I/O calls (e.g. fread(3)). * * SPE-side: * The SPE-side of this interface is implemented with a set of small stub * routines, which may be packaged into an SPE POSIX.1-compatible library. * These stubs are responsible for pushing SPE register parameters onto the * stack, and then executing a stop-and-signal instruction with a reserved * signal code (currently 0x2101). By convention, the next word following * the stop-and-signal instruction will contain the POSIX.1 op-code along * with a pointer to the beginning of the call stack frame. * * PPE-side: * The PPE application or library receives stop-and-signal notification * from the OS. The default_posix1_handler() routine is then called in order * to parse the POSIX.1 op-code and branch to a specific POSIX.1 handler, * such as default_posix1_handler_open(). * * The POSIX.1 handlers use direct-mapped access to LS in order to fetch * parameters from the stack frame, and to place return values (including * errno) into the expected locations. * * Errata: * This code is (hopefully) just temporary, until built-in OS support for * SPE syscalls is implemented. * * Enable SPE_POSIX1_SHM_CALLS if the various shm_ operations are needed * by the SPE. This requires applications link with -lrt, so it is * currently disabled by default, and will return ENOSYS back to the * SPE. */ #define SPE_POSIX1_OP_SHIFT 24 #define SPE_POSIX1_OP_MASK 0xff #define SPE_POSIX1_DATA_MASK 0xffffff #define SPE_POSIX1_OP(_v) (((_v) >> SPE_POSIX1_OP_SHIFT) & SPE_POSIX1_OP_MASK) #define SPE_POSIX1_DATA(_v) ((_v) & SPE_POSIX1_DATA_MASK) enum { SPE_POSIX1_ADJTIMEX=0x1, SPE_POSIX1_CLOSE, SPE_POSIX1_CREAT, SPE_POSIX1_FSTAT, SPE_POSIX1_FTOK , SPE_POSIX1_GETPAGESIZE, SPE_POSIX1_GETTIMEOFDAY, SPE_POSIX1_KILL, SPE_POSIX1_LSEEK, SPE_POSIX1_LSTAT, SPE_POSIX1_MMAP, SPE_POSIX1_MREMAP, SPE_POSIX1_MSYNC, SPE_POSIX1_MUNMAP, SPE_POSIX1_OPEN, SPE_POSIX1_READ, SPE_POSIX1_SHMAT, SPE_POSIX1_SHMCTL, SPE_POSIX1_SHMDT, SPE_POSIX1_SHMGET, SPE_POSIX1_SHM_OPEN, SPE_POSIX1_SHM_UNLINK, SPE_POSIX1_STAT, SPE_POSIX1_UNLINK, SPE_POSIX1_WAIT, SPE_POSIX1_WAITPID, SPE_POSIX1_WRITE, /* added to support fortran frontend */ SPE_POSIX1_FTRUNCATE, SPE_POSIX1_ACCESS, SPE_POSIX1_DUP, SPE_POSIX1_TIME, SPE_POSIX1_LAST_OPCODE, }; #define SPE_POSIX1_NR_OPCODES \ ((SPE_POSIX1_LAST_OPCODE - SPE_POSIX1_ADJTIMEX) + 1) #define CHECK_POSIX1_OPCODE(_op) \ if (SPE_POSIX1_OP(opdata) != SPE_POSIX1_ ## _op) { \ DEBUG_PRINTF("OPCODE (0x%x) mismatch.\n", SPE_POSIX1_OP(opdata)); \ return 1; \ } typedef union { unsigned long long all64; unsigned int by32[2]; } addr64; /* SPE-compatable stat structure. */ struct spe_compat_stat { unsigned int dev; unsigned int ino; unsigned int mode; unsigned int nlink; unsigned int uid; unsigned int gid; unsigned int rdev; unsigned int size; unsigned int blksize; unsigned int blocks; unsigned int atime; unsigned int mtime; unsigned int ctime; }; /* SPE-compatable timeval structure. */ struct spe_compat_timeval { int tv_sec; int tv_usec; }; /* SPE-compatable timezone structure. */ struct spe_compat_timezone { int tz_minuteswest; int tz_dsttime; }; /* SPE-compatable timex structure. */ struct spe_compat_timex { unsigned int modes; int offset; int freq; int maxerror; int esterror; int status; int constant; int precision; int tolerance; struct spe_compat_timeval time; int tick; int ppsfreq; int jitter; int shift; int stabil; int jitcnt; int calcnt; int errcnt; int stbcnt; int :32; int :32; int :32; int :32; int :32; int :32; int :32; int :32; int :32; int :32; int :32; int :32; }; /** * default_posix1_handler_stat * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int stat(const char *file_name, struct stat *buf) */ int default_posix1_handler_stat(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); struct stat buf; struct spe_compat_stat spe_buf; char *file_name; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(STAT); file_name = GET_LS_PTR(arg0->slot[0]); rc = stat(file_name, &buf); if (rc == 0) { spe_buf.dev = buf.st_dev; spe_buf.ino = buf.st_ino; spe_buf.mode = buf.st_mode; spe_buf.nlink = buf.st_nlink; spe_buf.uid = buf.st_uid; spe_buf.gid = buf.st_gid; spe_buf.rdev = buf.st_rdev; spe_buf.size = buf.st_size; spe_buf.blksize = buf.st_blksize; spe_buf.blocks = buf.st_blocks; spe_buf.atime = buf.st_atime; spe_buf.mtime = buf.st_mtime; spe_buf.ctime = buf.st_ctime; memcpy(GET_LS_PTR(arg1->slot[0]), &spe_buf, sizeof(spe_buf)); } PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_fstat * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int fstat(int filedes, struct stat *buf) */ int default_posix1_handler_fstat(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); struct stat buf; struct spe_compat_stat spe_buf; int filedes; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(FSTAT); filedes = arg0->slot[0]; rc = fstat(filedes, &buf); if (rc == 0) { spe_buf.dev = buf.st_dev; spe_buf.ino = buf.st_ino; spe_buf.mode = buf.st_mode; spe_buf.nlink = buf.st_nlink; spe_buf.uid = buf.st_uid; spe_buf.gid = buf.st_gid; spe_buf.rdev = buf.st_rdev; spe_buf.size = buf.st_size; spe_buf.blksize = buf.st_blksize; spe_buf.blocks = buf.st_blocks; spe_buf.atime = buf.st_atime; spe_buf.mtime = buf.st_mtime; spe_buf.ctime = buf.st_ctime; memcpy(GET_LS_PTR(arg1->slot[0]), &spe_buf, sizeof(spe_buf)); } PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_lstat * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int lstat(const char *file_name, struct stat *buf) */ int default_posix1_handler_lstat(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); struct stat buf; struct spe_compat_stat spe_buf; char *file_name; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(LSTAT); file_name = GET_LS_PTR(arg0->slot[0]); rc = lstat(file_name, &buf); if (rc == 0) { spe_buf.dev = buf.st_dev; spe_buf.ino = buf.st_ino; spe_buf.mode = buf.st_mode; spe_buf.nlink = buf.st_nlink; spe_buf.uid = buf.st_uid; spe_buf.gid = buf.st_gid; spe_buf.rdev = buf.st_rdev; spe_buf.size = buf.st_size; spe_buf.blksize = buf.st_blksize; spe_buf.blocks = buf.st_blocks; spe_buf.atime = buf.st_atime; spe_buf.mtime = buf.st_mtime; spe_buf.ctime = buf.st_ctime; memcpy(GET_LS_PTR(arg1->slot[0]), &spe_buf, sizeof(spe_buf)); } PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_open * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int open(const char *pathname, int flags, mode_t mode); */ int default_posix1_handler_open(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); char *pathname; int flags; mode_t mode; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(OPEN); pathname = GET_LS_PTR(arg0->slot[0]); flags = (int) arg1->slot[0]; mode = (mode_t) arg2->slot[0]; rc = open(pathname, flags, mode); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_access * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int access(const char *pathname, int mode); */ int default_posix1_handler_access(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); char *pathname; int mode; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(ACCESS); pathname = GET_LS_PTR(arg0->slot[0]); mode = (int) arg1->slot[0]; rc = access(pathname, mode); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_creat * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int creat(const char *pathname, mode_t mode); */ int default_posix1_handler_creat(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); char *pathname; mode_t mode; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(CREAT); pathname = GET_LS_PTR(arg0->slot[0]); mode = (mode_t) arg1->slot[0]; rc = creat(pathname, mode); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_close * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int close(int fd); */ int default_posix1_handler_close(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); int fd; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(CLOSE); fd = arg0->slot[0]; rc = close(fd); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_dup * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int dup(int oldfd); */ int default_posix1_handler_dup(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); int oldfd; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(DUP); oldfd = arg0->slot[0]; rc = dup(oldfd); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_time * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * time_t time(time_t *t); */ int default_posix1_handler_time(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); time_t *t; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(TIME); t = GET_LS_PTR(arg0->slot[0]); rc = time(t); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_read * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * ssize_t read(int fd, void *buf, size_t count); */ int default_posix1_handler_read(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); int fd; void *buf; size_t count; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(READ); fd = arg0->slot[0]; buf = GET_LS_PTR(arg1->slot[0]); count = arg2->slot[0]; rc = read(fd, buf, count); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_write * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * ssize_t write(int fd, const void *buf, size_t count); */ int default_posix1_handler_write(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); int fd; void *buf; size_t count; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(WRITE); fd = arg0->slot[0]; buf = GET_LS_PTR(arg1->slot[0]); count = arg2->slot[0]; rc = write(fd, buf, count); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_lseek * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * off_t lseek(int fildes, off_t offset, int whence); */ int default_posix1_handler_lseek(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); int fildes; off_t offset; int whence; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(LSEEK); fildes = arg0->slot[0]; offset = (off_t) arg1->slot[0]; whence = arg2->slot[0]; rc = lseek(fildes, offset, whence); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_ftruncate * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int ftruncate(int fd, off_t length); * */ int default_posix1_handler_ftruncate(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); int fd; off_t length; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(FTRUNCATE); fd = arg0->slot[0]; length = (off_t) arg1->slot[0]; rc = ftruncate(fd, length); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_unlink * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int unlink(const char *pathname); */ int default_posix1_handler_unlink(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); char *pathname; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(UNLINK); pathname = GET_LS_PTR(arg0->slot[0]); rc = unlink(pathname); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_mmap * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * void *mmap(void *start, size_t length, int prot , int flags, * int fd, off_t offset); * * Both 'start' and 'addr' (returned) are treated as 64b EA pointers * rather than LS offsets. On powerpc32 ABI (which is ILP-32), these * are handled as 32b EA pointers. */ int default_posix1_handler_mmap(char *ls, unsigned long opdata) { DECL_6_ARGS(); DECL_RET(); addr64 start; size_t length; int prot; int flags; int fd; off_t offset; void *mmap_addr; addr64 addr; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(MMAP); start.by32[0] = arg0->slot[0]; start.by32[1] = arg0->slot[1]; length = (size_t) arg1->slot[0]; prot = arg2->slot[0]; flags = arg3->slot[0]; fd = arg4->slot[0]; offset = (off_t) arg5->slot[0]; mmap_addr = mmap((void *) ((unsigned long) start.all64), length, prot, flags, fd, offset); if (mmap_addr == MAP_FAILED) { addr.all64 = -1LL; } else { addr.all64 = (unsigned long long) (unsigned long) mmap_addr; } PUT_LS_RC(addr.by32[0], addr.by32[1], 0, errno); return 0; } /** * default_posix1_handler_munmap * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int munmap(void *start, size_t length); * * For this interface, 'start' is taken to be an EA pointer * rather than an LS offset. */ int default_posix1_handler_munmap(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); addr64 start; size_t length; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(MUNMAP); start.by32[0] = arg0->slot[0]; start.by32[1] = arg0->slot[1]; length = (size_t) arg1->slot[0]; rc = munmap((void *) ((unsigned long) start.all64), length); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_mremap * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * void *mremap(void *old_address, size_t old_size, * size_t new_size, unsigned long flags); * * For this interface, both 'old_address' and the returned value * are taken to be EA pointers, rather than LS offsets. */ int default_posix1_handler_mremap(char *ls, unsigned long opdata) { DECL_4_ARGS(); DECL_RET(); addr64 old_address; size_t old_size; size_t new_size; unsigned long flags; addr64 addr; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(MREMAP); old_address.by32[0] = arg0->slot[0]; old_address.by32[1] = arg0->slot[1]; old_size = (size_t) arg1->slot[0]; new_size = (size_t) arg2->slot[0]; flags = (unsigned long) arg3->slot[0]; addr.all64 = (unsigned long) mremap((void *) ((unsigned long) old_address.all64), old_size, new_size, flags); PUT_LS_RC(addr.by32[0], addr.by32[1], 0, errno); return 0; } /** * default_posix1_handler_msync * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int msync(const void *start, size_t length, int flags); * * For this interface, 'start' is taken to be an EA pointer * rather than an LS offset. */ int default_posix1_handler_msync(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); addr64 start; size_t length; int flags; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(MSYNC); start.by32[0] = arg0->slot[0]; start.by32[1] = arg0->slot[1]; length = (size_t) arg1->slot[0]; flags = arg2->slot[0]; rc = msync((void *) ((unsigned long) start.all64), length, flags); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_shm_open * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * void *shm_open(const char *name, int oflag, mode_t mode); * * For this interface, the returned value is taken to be an * EA pointer rather than an LS offset. */ int default_posix1_handler_shm_open(char *ls, unsigned long opdata) { #ifdef SPE_POSIX1_SHM_CALLS DECL_3_ARGS(); DECL_RET(); unsigned char *name; int oflag; mode_t mode; unsigned long addr; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(SHM_OPEN); name = GET_LS_PTR(arg0->slot[0]); oflag = (int) arg1->slot[0]; mode = (mode_t) arg2->slot[0]; addr = (unsigned long) shm_open(name, oflag, mode); PUT_LS_RC(addr, 0, 0, errno); #else DECL_0_ARGS(); DECL_RET(); CHECK_POSIX1_OPCODE(SHM_OPEN); PUT_LS_RC(0, 0, 0, ENOSYS); #endif return 0; } /** * default_posix1_handler_shm_unlink * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int shm_unlink(const char *name); */ int default_posix1_handler_shm_unlink(char *ls, unsigned long opdata) { #ifdef SPE_POSIX1_SHM_CALLS DECL_1_ARGS(); DECL_RET(); unsigned char *name; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(SHM_UNLINK); name = GET_LS_PTR(arg0->slot[0]); rc = shm_unlink(name); PUT_LS_RC(rc, 0, 0, errno); #else DECL_0_ARGS(); DECL_RET(); CHECK_POSIX1_OPCODE(SHM_UNLINK); PUT_LS_RC(-1, 0, 0, ENOSYS); #endif return 0; } /** * default_posix1_handler_shmat * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * void *shmat(int shmid, const void *shmaddr, int shmflg); * * For this interface, both 'shmaddr' and the returned value are * taken to be EA pointers rather than LS offsets. */ int default_posix1_handler_shmat(char *ls, unsigned long opdata) { #ifdef SPE_POSIX1_SHM_CALLS DECL_3_ARGS(); DECL_RET(); int shmid; addr64 shmaddr; int shmflg; addr64 addr; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(SHMAT); shmid = arg0->slot[0]; shmaddr.by32[0] = arg1->slot[0]; shmaddr.by32[1] = arg1->slot[1]; shmflg = arg2->slot[0]; addr.all64 = (unsigned long) shmat(shmid, (void *)((unsigned long)shmaddr.all64), shmflg); PUT_LS_RC(addr.by32[0], addr.by32[1], 0, errno); #else DECL_0_ARGS(); DECL_RET(); CHECK_POSIX1_OPCODE(SHMAT); PUT_LS_RC(0, 0, 0, ENOSYS); #endif return 0; } /** * default_posix1_handler_shmdt * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int shmdt(const void *shmaddr); * * For this interface 'shmaddr' is taken to be an EA pointer * rather than an LS offset. */ int default_posix1_handler_shmdt(char *ls, unsigned long opdata) { #ifdef SPE_POSIX1_SHM_CALLS DECL_1_ARGS(); DECL_RET(); addr64 shmaddr; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(SHMDT); shmaddr.by32[0] = arg0->slot[0]; shmaddr.by32[1] = arg0->slot[1]; rc = shmdt((void *) ((unsigned long) shmaddr.all64)); PUT_LS_RC(rc, 0, 0, errno); #else DECL_0_ARGS(); DECL_RET(); CHECK_POSIX1_OPCODE(SHMDT); PUT_LS_RC(-1, 0, 0, ENOSYS); #endif return 0; } /** * default_posix1_handler_shmctl * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int shmctl(int shmid, int cmd, struct shmid_ds *buf); * * For this interface 'buf' is taken to be an EA pointer rather * than an LS offset. */ int default_posix1_handler_shmctl(char *ls, unsigned long opdata) { #ifdef SPE_POSIX1_SHM_CALLS DECL_3_ARGS(); DECL_RET(); int shmid; int cmd; addr64 buf; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(SHMCTL); shmid = arg0->slot[0]; cmd = arg1->slot[0]; buf.by32[0] = arg2->slot[0]; buf.by32[1] = arg2->slot[1]; rc = shmctl(shmid, cmd, (struct shmid_ds *) ((unsigned long) buf.all64)); PUT_LS_RC(rc, 0, 0, errno); #else DECL_0_ARGS(); DECL_RET(); CHECK_POSIX1_OPCODE(SHMCTL); PUT_LS_RC(-1, 0, 0, ENOSYS); #endif return 0; } /** * default_posix1_handler_shmget * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int shmget(key_t key, int size, int shmflg); */ int default_posix1_handler_shmget(char *ls, unsigned long opdata) { #ifdef SPE_POSIX1_SHM_CALLS DECL_3_ARGS(); DECL_RET(); key_t key; int size; int shmflg; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(SHMGET); key = (key_t) arg0->slot[0]; size = arg1->slot[0]; shmflg = arg2->slot[0]; rc = shmget(key, size, shmflg); PUT_LS_RC(rc, 0, 0, errno); #else DECL_0_ARGS(); DECL_RET(); CHECK_POSIX1_OPCODE(SHMGET); PUT_LS_RC(-1, 0, 0, ENOSYS); #endif return 0; } /** * default_posix1_handler_ftok * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * key_t ftok(const char *pathname, int proj_id); * * For convenience, this function takes 'pathname' to be the LS * offset of a NULL-terminated character string. */ int default_posix1_handler_ftok(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); char *pathname; int proj_id; key_t rc; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(FTOK); pathname = GET_LS_PTR(arg0->slot[0]); proj_id = arg1->slot[0]; rc = ftok(pathname, proj_id); PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_getpagesize * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int getpagesize(void); */ int default_posix1_handler_getpagesize(char *ls, unsigned long opdata) { DECL_0_ARGS(); DECL_RET(); int sz; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(GETPAGESIZE); sz = getpagesize(); PUT_LS_RC(sz, 0, 0, 0); return 0; } /** * default_posix1_handler_wait * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * pid_t wait(int *status) */ int default_posix1_handler_wait(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); int *status; pid_t pid; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(WAIT); status = (int *) GET_LS_PTR(arg0->slot[0]); pid = wait(status); PUT_LS_RC(pid, 0, 0, errno); return 0; } /** * default_posix1_handler_waitpid * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * pid_t waitpid(pid_t pid, int *status, int options) */ int default_posix1_handler_waitpid(char *ls, unsigned long opdata) { DECL_3_ARGS(); DECL_RET(); pid_t pid; int *status; int options; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(WAIT); pid = arg0->slot[0]; status = (int *) GET_LS_PTR(arg1->slot[0]); options = arg2->slot[0]; pid = waitpid(pid, status, options); PUT_LS_RC(pid, 0, 0, errno); return 0; } /** * default_posix1_handler_kill * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int kill(pid_t pid, int sig) */ int default_posix1_handler_kill(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); pid_t pid; int sig; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(KILL); pid = arg0->slot[0]; sig = arg1->slot[0]; rc = kill(pid, sig); PUT_LS_RC(rc, 0, 0, errno); return 0; } #define _COPY_TIMEX_FIELD(_dst, _src, _field) \ (_dst)->_field = (_src)->_field #define _COPY_TIMEX_STRUCT(_dst, _src) \ _COPY_TIMEX_FIELD(_dst, _src, modes); \ _COPY_TIMEX_FIELD(_dst, _src, offset); \ _COPY_TIMEX_FIELD(_dst, _src, freq); \ _COPY_TIMEX_FIELD(_dst, _src, maxerror); \ _COPY_TIMEX_FIELD(_dst, _src, esterror); \ _COPY_TIMEX_FIELD(_dst, _src, status); \ _COPY_TIMEX_FIELD(_dst, _src, constant); \ _COPY_TIMEX_FIELD(_dst, _src, precision); \ _COPY_TIMEX_FIELD(_dst, _src, tolerance); \ _COPY_TIMEX_FIELD(_dst, _src, time.tv_sec); \ _COPY_TIMEX_FIELD(_dst, _src, time.tv_usec); \ _COPY_TIMEX_FIELD(_dst, _src, tick); \ _COPY_TIMEX_FIELD(_dst, _src, ppsfreq); \ _COPY_TIMEX_FIELD(_dst, _src, jitter); \ _COPY_TIMEX_FIELD(_dst, _src, shift); \ _COPY_TIMEX_FIELD(_dst, _src, stabil); \ _COPY_TIMEX_FIELD(_dst, _src, jitcnt); \ _COPY_TIMEX_FIELD(_dst, _src, calcnt); \ _COPY_TIMEX_FIELD(_dst, _src, errcnt); \ _COPY_TIMEX_FIELD(_dst, _src, stbcnt) /** * default_posix1_handler_adjtimex * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE adjtimex library operation: * * int adjtimex(struct timex *buf) */ int default_posix1_handler_adjtimex(char *ls, unsigned long opdata) { DECL_1_ARGS(); DECL_RET(); struct spe_compat_timex *buf; struct timex local; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(ADJTIMEX); buf = (struct spe_compat_timex *) GET_LS_PTR(arg0->slot[0]); _COPY_TIMEX_STRUCT(&local, buf); rc = adjtimex(&local); if (rc==0) { _COPY_TIMEX_STRUCT(buf, &local); } PUT_LS_RC(rc, 0, 0, errno); return 0; } /** * default_posix1_handler_gettimeofday * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * SPE POSIX.1 library operation, per: POSIX.1 (IEEE Std 1003.1), * implementing: * * int gettimeofday(struct timeval *tv, struct timezone *tz) */ int default_posix1_handler_gettimeofday(char *ls, unsigned long opdata) { DECL_2_ARGS(); DECL_RET(); struct spe_compat_timeval *tv; struct spe_compat_timezone *tz; struct timeval t; struct timezone zone; int rc; DEBUG_PRINTF("%s\n", __func__); CHECK_POSIX1_OPCODE(GETTIMEOFDAY); tv = (struct spe_compat_timeval *) GET_LS_PTR(arg0->slot[0]); tz = (struct spe_compat_timezone *) GET_LS_PTR(arg1->slot[0]); rc = gettimeofday(&t, &zone); if (rc==0) { if (arg0->slot[0] != 0) { tv->tv_sec = t.tv_sec; tv->tv_usec = t.tv_usec; } if (arg1->slot[0] != 0) { tz->tz_minuteswest = zone.tz_minuteswest; } } PUT_LS_RC(rc, 0, 0, errno); return 0; } int (*default_posix1_funcs[SPE_POSIX1_NR_OPCODES]) (char *, unsigned long) = { default_posix1_handler_adjtimex, default_posix1_handler_close, default_posix1_handler_creat, default_posix1_handler_fstat, default_posix1_handler_ftok, default_posix1_handler_getpagesize, default_posix1_handler_gettimeofday, default_posix1_handler_kill, default_posix1_handler_lseek, default_posix1_handler_lstat, default_posix1_handler_mmap, default_posix1_handler_mremap, default_posix1_handler_msync, default_posix1_handler_munmap, default_posix1_handler_open, default_posix1_handler_read, default_posix1_handler_shmat, default_posix1_handler_shmctl, default_posix1_handler_shmdt, default_posix1_handler_shmget, default_posix1_handler_shm_open, default_posix1_handler_shm_unlink, default_posix1_handler_stat, default_posix1_handler_unlink, default_posix1_handler_wait, default_posix1_handler_waitpid, default_posix1_handler_write, default_posix1_handler_ftruncate, default_posix1_handler_access, default_posix1_handler_dup, default_posix1_handler_time, }; /** * default_posix1_handler * @ls: base pointer to local store area. * @opdata: POSIX.1 call opcode & data. * * Default POSIX.1 call dispatch function. */ int default_posix1_handler(char *base, unsigned long offset) { int op, opdata; if (!base) { DEBUG_PRINTF("%s: mmap LS required.\n", __func__); return 1; } offset = (offset & LS_ADDR_MASK) & ~0x1; opdata = *((int *)((char *) base + offset)); op = SPE_POSIX1_OP(opdata); if ((op <= 0) || (op >= SPE_POSIX1_NR_OPCODES)) { DEBUG_PRINTF("%s: Unhandled type opdata=%08x op=%08x\n", __func__, opdata, SPE_POSIX1_OP(opdata)); return 1; } default_posix1_funcs[op-1] (base, opdata); return 0; } libspe-1.2.2/default_posix1_handler.h0000640000076400007640000000632110533602311017353 0ustar cellbldcellbld/* default_c99_handler.h - emulate SPE C99 library calls. * * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __DEFAULT_POSIX1_HANDLER_H__ #define __DEFAULT_POSIX1_HANDLER_H__ #define SPE_POSIX1_CLASS 0x2101 extern int default_posix1_handler(char *ls, unsigned long args); extern int default_posix1_handler_adjtimex(char *ls, unsigned long args); extern int default_posix1_handler_close(char *ls, unsigned long args); extern int default_posix1_handler_creat(char *ls, unsigned long args); extern int default_posix1_handler_fstat(char *ls, unsigned long args); extern int default_posix1_handler_ftok(char *ls, unsigned long args); extern int default_posix1_handler_getpagesize(char *ls, unsigned long args); extern int default_posix1_handler_gettimeofday(char *ls, unsigned long args); extern int default_posix1_handler_kill(char *ls, unsigned long args); extern int default_posix1_handler_lseek(char *ls, unsigned long args); extern int default_posix1_handler_lstat(char *ls, unsigned long args); extern int default_posix1_handler_mmap(char *ls, unsigned long args); extern int default_posix1_handler_mremap(char *ls, unsigned long args); extern int default_posix1_handler_msync(char *ls, unsigned long args); extern int default_posix1_handler_munmap(char *ls, unsigned long args); extern int default_posix1_handler_open(char *ls, unsigned long args); extern int default_posix1_handler_read(char *ls, unsigned long args); extern int default_posix1_handler_shmat(char *ls, unsigned long args); extern int default_posix1_handler_shmctl(char *ls, unsigned long args); extern int default_posix1_handler_shmdt(char *ls, unsigned long args); extern int default_posix1_handler_shmget(char *ls, unsigned long args); extern int default_posix1_handler_shm_open(char *ls, unsigned long args); extern int default_posix1_handler_shm_unlink(char *ls, unsigned long args); extern int default_posix1_handler_stat(char *ls, unsigned long args); extern int default_posix1_handler_unlink(char *ls, unsigned long args); extern int default_posix1_handler_wait(char *ls, unsigned long args); extern int default_posix1_handler_waitpid(char *ls, unsigned long args); extern int default_posix1_handler_write(char *ls, unsigned long args); extern int default_posix1_handler_ftruncate(char *ls, unsigned long args); extern int default_posix1_handler_access(char *ls, unsigned long args); extern int default_posix1_handler_dup(char *ls, unsigned long args); extern int default_posix1_handler_time(char *ls, unsigned long args); #endif /* __DEFAULT_POSIX1_HANDLER_H__ */ libspe-1.2.2/default_syscall_handler.c0000640000076400007640000001316310533602311017577 0ustar cellbldcellbld/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #define __PRINTF(fmt, args...) { fprintf(stderr,fmt , ## args); } #ifdef DEBUG #define DEBUG_PRINTF(fmt, args...) __PRINTF(fmt , ## args) #else #define DEBUG_PRINTF(fmt, args...) #endif int default_syscall_handler_write (unsigned char *base, syscall_write_t * ps) { void *buf; buf = base + ps->ptr; DEBUG_PRINTF ("default_syscall_handler: write( %d, %016lx, %d) \n", ps->fd, (unsigned long) buf, ps->len); ps->rc = write (ps->fd, buf, ps->len); ps->err = errno; return (0); } int default_syscall_handler_read (unsigned char *base, syscall_read_t * ps) { void *buf; buf = base + ps->ptr; DEBUG_PRINTF ("default_syscall_handler: read( %d, %016lx, %d) \n", ps->fd, (unsigned long) buf, ps->len); ps->rc = read (ps->fd, buf, ps->len); ps->err = errno; return (0); } int default_syscall_handler_open (unsigned char *base, syscall_open_t * ps) { char *buf; int flags; buf = (char *) base + ps->pathname; DEBUG_PRINTF ("default_syscall_handler: open flags=%08x \n", ps->flags); flags = O_RDONLY; /* TODO: map all internal/newlib flags to the host flags */ if (ps->flags & 0x2) { /* newlib O_RDWR */ DEBUG_PRINTF ("default_syscall_handler: O_RDWR\n"); flags |= O_RDWR; } if (ps->flags & 0x8) { /* newlib O_APPEND */ flags |= O_APPEND; } if (ps->flags & 0x200) { /* newlib O_CREAT */ DEBUG_PRINTF ("default_syscall_handler: O_CREAT\n"); flags |= O_CREAT; } if (ps->flags & 0x400) { /* newlib O_TRUNC */ DEBUG_PRINTF ("default_syscall_handler: O_TRUNC\n"); flags |= O_TRUNC; } if (ps->flags & 0x800) { /* newlib O_EXCL */ flags |= O_EXCL; } if (ps->flags & 0x2000) { /* newlib O_SYNC */ DEBUG_PRINTF ("default_syscall_handler: O_SYNC\n"); flags |= O_SYNC; } if (ps->flags & 0x4000) { /* newlib O_NOBLOCK */ //flags |= O_NOBLOCK; } if (ps->flags & 0x8000) { /* newlib O_NOCTTY */ flags |= O_NOCTTY; } DEBUG_PRINTF ("default_syscall_handler: open( \"%s\", %x, %x) \n", buf, flags, ps->mode); ps->rc = open (buf, flags, ps->mode); ps->err = errno; #ifdef DEBUG if (ps->rc == -1) { DEBUG_PRINTF ("\trc=%d, errno=%d -> %s\n", ps->rc, ps->err, strerror (errno)); } #endif return (0); } int default_syscall_handler_close (unsigned char *base, syscall_close_t * ps) { ps->rc = close (ps->fd); ps->err = errno; return (0); } int default_syscall_handler_lseek (unsigned char *base, syscall_lseek_t * ps) { DEBUG_PRINTF ("default_syscall_handler: lseek( %ld, %ld, %d) \n", ps->fd, ps->offset, ps->whence); ps->rc = lseek (ps->fd, ps->offset, ps->whence); ps->err = errno; return (0); } int default_syscall_handler_fstat (unsigned char *base, syscall_fstat_t * ps) { struct stat buf; void *spebuf; spebuf = base + (unsigned long) (ps->buf); ps->rc = fstat (ps->fd, &buf); ps->err = errno; //memcpy (spebuf, &buf, sizeof (struct stat)); return (0); } int default_syscall_handler_unlink (unsigned char *base, syscall_unlink_t * ps) { char *buf; buf = (char *) base + (unsigned long) (ps->pathname); ps->rc = unlink (buf); ps->err = errno; return (0); } int default_syscall_handler (unsigned long *base, unsigned long args) { syscall_t *ps; DEBUG_PRINTF ("default_syscall_handler: base %016lx, args %08lx\n", (unsigned long) base, args); if (!base) { printf ("No MMAPed spe not supported yet.\n"); return (-1); } ps = (syscall_t *) ((unsigned char *) base + args); switch (ps->no) { case SYS_WRITE: default_syscall_handler_write ((unsigned char *) base, (syscall_write_t *) ps); break; case SYS_READ: default_syscall_handler_read ((unsigned char *) base, (syscall_read_t *) ps); break; case SYS_OPEN: default_syscall_handler_open ((unsigned char *) base, (syscall_open_t *) ps); break; case SYS_CLOSE: default_syscall_handler_close ((unsigned char *) base, (syscall_close_t *) ps); break; case SYS_SEEK: default_syscall_handler_lseek ((unsigned char *) base, (syscall_lseek_t *) ps); break; case SYS_FSTAT: default_syscall_handler_fstat ((unsigned char *) base, (syscall_fstat_t *) ps); break; case SYS_UNLINK: default_syscall_handler_unlink ((unsigned char *) base, (syscall_unlink_t *) ps); break; default: /* we don't know how to handle this */ DEBUG_PRINTF ("default_syscall_handler: Unhandled type %08x\n", ps->no); return (1); /* give the next handler a chance */ } DEBUG_PRINTF ("default_syscall_handler: DONE -> rc=%d\n", ps->rc); return (0); /* we handled it, no further processing needed */ } libspe-1.2.2/default_syscall_handler.h0000640000076400007640000000534610533602310017607 0ustar cellbldcellbld/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __DEFAULT_SYSCALL_HANDLER #define __DEFAULT_SYSCALL_HANDLER #define SYS_OPEN 0x0101 #define SYS_CLOSE 0x0102 #define SYS_READ 0x0103 #define SYS_WRITE 0x0104 #define SYS_SEEK 0x0105 #define SYS_FSTAT 0x0106 #define SYS_UNLINK 0x0107 typedef struct { unsigned short no; short rc; unsigned short err; unsigned char pad[64 - 3 * 2]; } syscall_t; typedef struct { unsigned short no; short rc; unsigned short err; int fd; unsigned long ptr; int len; } syscall_write_t; typedef struct { unsigned short no; short rc; unsigned short err; int fd; unsigned long ptr; int len; } syscall_read_t; typedef struct { unsigned short no; short rc; unsigned short err; unsigned long fd; unsigned long pathname; unsigned short flags; unsigned short mode; } syscall_open_t; typedef struct { unsigned short no; short rc; unsigned short err; unsigned long fd; } syscall_close_t; typedef struct { unsigned short no; short rc; unsigned short err; unsigned long fd; unsigned long offset; unsigned char whence; } syscall_lseek_t; typedef struct { unsigned short no; short rc; unsigned short err; unsigned long fd; void *buf; } syscall_fstat_t; typedef struct { unsigned short no; short rc; unsigned short err; char *pathname; } syscall_unlink_t; int default_syscall_handler (unsigned long *base, unsigned long args); int default_syscall_handler_write (unsigned char *base, syscall_write_t * ps); int default_syscall_handler_read (unsigned char *base, syscall_read_t * ps); int default_syscall_handler_open (unsigned char *base, syscall_open_t * ps); int default_syscall_handler_close (unsigned char *base, syscall_close_t * ps); int default_syscall_handler_lseek (unsigned char *base, syscall_lseek_t * ps); int default_syscall_handler_fstat (unsigned char *base, syscall_fstat_t * ps); int default_syscall_handler_unlink (unsigned char *base, syscall_unlink_t * ps); #endif libspe-1.2.2/dma.c0000640000076400007640000001401010533602311013455 0ustar cellbldcellbld/* libspe - A wrapper library to adapt the JSRE SPE usage model to SPUFS * Copyright (C) 2005 IBM Corp. * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "spe.h" #define __PRINTF(fmt, args...) { fprintf(stderr,fmt , ## args); } #ifdef DEBUG #define DEBUG_PRINTF(fmt, args...) __PRINTF(fmt , ## args) #else #define DEBUG_PRINTF(fmt, args...) #endif struct mfc_command_parameter_area { uint32_t pad; /* reserved */ uint32_t lsa; /* local storage address */ uint64_t ea; /* effective address */ uint16_t size; /* transfer size */ uint16_t tag; /* command tag */ uint16_t class; /* class ID */ uint16_t cmd; /* command opcode */ }; enum mfc_cmd { MFC_CMD_PUT = 0x20, MFC_CMD_PUTB = 0x21, MFC_CMD_PUTF = 0x22, MFC_CMD_GET = 0x40, MFC_CMD_GETB = 0x41, MFC_CMD_GETF = 0x42, }; static int spe_do_mfc_put(speid_t spe, unsigned src, void *dst, unsigned size, unsigned tag, unsigned class, enum mfc_cmd cmd) { struct thread_store *thread_store = spe; struct mfc_command_parameter_area parm = { .lsa = src, .ea = (unsigned long) dst, .size = size, .tag = tag, .class = class, .cmd = cmd, }; int ret; DEBUG_PRINTF("queuing DMA %x %lx %x %x %x %x\n", parm.lsa, parm.ea, parm.size, parm.tag, parm.class, parm.cmd); if (!srch_thread(spe)) return -1; if (thread_store->fd_mfc == -1) { /* the kernel does not support DMA, so just copy directly */ memcpy(dst, thread_store->mem_mmap_base + src, size); return 0; } ret = write(thread_store->fd_mfc, &parm, sizeof (parm)); if ((ret < 0) && (errno != EIO)) { perror("spe_do_mfc_put: internal error"); } return ret < 0 ? -1 : 0; } static int spe_do_mfc_get(speid_t spe, unsigned dst, void *src, unsigned size, unsigned tag, unsigned class, enum mfc_cmd cmd) { struct thread_store *thread_store = spe; struct mfc_command_parameter_area parm = { .lsa = dst, .ea = (unsigned long) src, .size = size, .tag = tag, .class = class, .cmd = cmd, }; int ret; DEBUG_PRINTF("queuing DMA %x %lx %x %x %x %x\n", parm.lsa, parm.ea, parm.size, parm.tag, parm.class, parm.cmd); if (!srch_thread(spe)) return -1; if (thread_store->fd_mfc == -1) { /* the kernel does not support DMA, so just copy directly */ memcpy(thread_store->mem_mmap_base + dst, src, size); return 0; } ret = write(thread_store->fd_mfc, &parm, sizeof (parm)); if ((ret < 0) && (errno != EIO)) { perror("spe_do_mfc_get: internal error"); } return ret < 0 ? -1 : 0; } int spe_mfc_put (speid_t spe, unsigned src, void *dst, unsigned size, unsigned short tag, unsigned char tid, unsigned char rid) { return spe_do_mfc_put(spe, src, dst, size, tag & 0xf, tid << 8 | rid, MFC_CMD_PUT); } int spe_mfc_putf(speid_t spe, unsigned src, void *dst, unsigned size, unsigned short tag, unsigned char tid, unsigned char rid) { return spe_do_mfc_put(spe, src, dst, size, tag & 0xf, tid << 8 | rid, MFC_CMD_PUTF); } int spe_mfc_putb(speid_t spe, unsigned src, void *dst, unsigned size, unsigned short tag, unsigned char tid, unsigned char rid) { return spe_do_mfc_put(spe, src, dst, size, tag & 0xf, tid << 8 | rid, MFC_CMD_PUTB); } int spe_mfc_get (speid_t spe, unsigned dst, void *src, unsigned size, unsigned short tag, unsigned char tid, unsigned char rid) { return spe_do_mfc_get(spe, dst, src, size, tag & 0xf, tid << 8 | rid, MFC_CMD_GET); } int spe_mfc_getf(speid_t spe, unsigned dst, void *src, unsigned size, unsigned short tag, unsigned char tid, unsigned char rid) { return spe_do_mfc_get(spe, dst, src, size, tag & 0xf, tid << 8 | rid, MFC_CMD_GETF); } int spe_mfc_getb(speid_t spe, unsigned dst, void *src, unsigned size, unsigned short tag, unsigned char tid, unsigned char rid) { return spe_do_mfc_get(spe, dst, src, size, tag & 0xf, tid << 8 | rid, MFC_CMD_GETB); } /* MFC Read tag status functions * */ static int read_tag_status_noblock(speid_t speid) { struct thread_store *spe = speid; int r_read = 0; unsigned int ret; r_read = read(spe->fd_mfc,&ret,4); if (r_read == 4) { return ret; } return -1; } static int read_tag_status_async(speid_t speid) { struct thread_store *spe = speid; struct pollfd poll_fd; int r_read = 0; unsigned int ret; poll_fd.fd = spe->fd_mfc; poll_fd.events = POLLIN; ret = poll(&poll_fd, 1, -1); if (ret < 0 || !(poll_fd.revents | POLLIN)) return -1; r_read = read(spe->fd_mfc,&ret,4); if (r_read == 4) { return ret; } return -1; } int spe_mfc_read_tag_status_all(speid_t speid, unsigned int mask) { int status; if ((status = read_tag_status_noblock(speid)) == -1) return -1; while ((status & mask) != mask) { if ((status = read_tag_status_async(speid)) == -1) return -1; } return status & mask; } int spe_mfc_read_tag_status_any(speid_t speid, unsigned int mask) { int status; if ((status = read_tag_status_noblock(speid)) == -1) return -1; while ((status & mask) == 0) { if ((status = read_tag_status_async(speid)) == -1) return -1; } return status & mask; } int spe_mfc_read_tag_status_immediate(speid_t speid, unsigned int mask) { int status; if ((status = read_tag_status_noblock(speid)) == -1) return -1; return status & mask ; } libspe-1.2.2/doc/0000755000076400007640000000000010575455116013344 5ustar cellbldcellbldlibspe-1.2.2/doc/Doxyfile0000640000076400007640000013523510533602312015041 0ustar cellbldcellbld# Doxyfile 1.3.9.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = libspe # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = 1.2 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of source # files, where putting all generated files in the same directory would otherwise # cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, # Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, # Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, # Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, # Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # This tag can be used to specify the encoding used in the generated output. # The encoding is not always determined by the language that is chosen, # but also whether or not the output is meant for Windows or non-Windows users. # In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES # forces the Windows encoding (this is the default for the Windows binary), # whereas setting the tag to NO uses a Unix-style encoding (the default for # all platforms other than Windows). USE_WINDOWS_ENCODING = NO # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is used # as the annotated text. Otherwise, the brief description is used as-is. If left # blank, the following values are used ("$name" is automatically replaced with the # name of the entity): "The $name class" "The $name widget" "The $name file" # "is" "provides" "specifies" "contains" "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited # members of a class in the documentation of that class as if those members were # ordinary class members. Constructors, destructors and assignment operators of # the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like the Qt-style comments (thus requiring an # explicit @brief command for a brief description. JAVADOC_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. # If set to NO, the detailed description appears after the member # documentation. DETAILS_AT_TOP = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources # only. Doxygen will then generate output that is more tailored for Java. # For instance, namespaces will be presented as packages, qualified scopes # will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = YES # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = YES # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. SHOW_DIRECTORIES = NO #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = #INPUT = doc/design.txt spebase speevent spethread spegang # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp # *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories # that are symbolic links (a Unix filesystem feature) are excluded from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. EXCLUDE_PATTERNS = default* # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = $(HOME)/workspace/head-libspe2/tests # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = $(HOME) # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = YES # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = YES # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = doc/LatexHeader # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = YES #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = YES # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_PREDEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse the # parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or # super classes. Setting the tag to NO turns the diagrams off. Note that this # option is superseded by the HAVE_DOT option below. This is only a fallback. It is # recommended to install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = YES # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = YES # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will # generate a call dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected # functions only using the \callgraph command. CALL_GRAPH = YES # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found on the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_WIDTH = 1024 # The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_HEIGHT = 1024 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes that # lay further from the root node will be omitted. Note that setting this option to # 1 or 2 may greatly reduce the computation time needed for large code bases. Also # note that a graph may be further truncated if the graph's image dimensions are # not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). # If 0 is used for the depth value (the default), the graph is not depth-constrained. MAX_DOT_GRAPH_DEPTH = 0 # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO libspe-1.2.2/doc/LatexHeader0000640000076400007640000000225410533602312015436 0ustar cellbldcellbld\documentclass[a4paper]{book} \usepackage{a4wide} \usepackage{makeidx} \usepackage{fancyhdr} \usepackage{graphicx} \usepackage{multicol} \usepackage{float} \usepackage{textcomp} \usepackage{alltt} \usepackage{times} \ifx\pdfoutput\undefined \usepackage[ps2pdf, pagebackref=true, colorlinks=true, linkcolor=blue ]{hyperref} \usepackage{pspicture} \else \usepackage[pdftex, pagebackref=true, colorlinks=true, linkcolor=blue ]{hyperref} \fi \usepackage{../doc/doxygen} \makeindex \setcounter{tocdepth}{1} \renewcommand{\footrulewidth}{0.4pt} \begin{document} \begin{titlepage} \begin{flushleft} \rule{15cm}{1mm} \huge SPE Runtime Management Library \end{flushleft} \begin{flushleft} \vspace*{5cm} \rule{15cm}{1mm} \LARGE Version 1.2 \end{flushleft} \begin{flushright} \vspace*{4cm} \Large CBEA JSRE Series\\ \normalsize Cell Broadband Engine Architecture\\ Joint Software Reference Environment Series\\ \end{flushright} \begin{flushleft} \vspace*{6cm} \today \end{flushleft} \end{titlepage} \clearemptydoublepage \pagenumbering{roman} \tableofcontents \clearemptydoublepage \pagenumbering{arabic} libspe-1.2.2/doc/extractfunctions.xslt0000640000076400007640000000103710533602312017642 0ustar cellbldcellbld ; libspe-1.2.2/doc/doxygen.sty0000640000076400007640000000365210533602312015546 0ustar cellbldcellbld\NeedsTeXFormat{LaTeX2e} \ProvidesPackage{doxygen} \RequirePackage{calc} \RequirePackage{array} \pagestyle{fancyplain} \newcommand{\clearemptydoublepage}{\newpage{\pagestyle{empty}\cleardoublepage}} \renewcommand{\chaptermark}[1]{\markboth{#1}{}} \renewcommand{\sectionmark}[1]{\markright{\thesection\ #1}} \lhead[\fancyplain{}{\bfseries\thepage}] {\fancyplain{}{\bfseries\rightmark}} \rhead[\fancyplain{}{\bfseries\leftmark}] {\fancyplain{}{\bfseries\thepage}} \rfoot[\fancyplain{}{\bfseries\scriptsize SPE Runtime Management Library, Version 1.2 }]{} \lfoot[]{\fancyplain{}{\bfseries\scriptsize SPE Runtime Management Library, Version 1.2 }} \cfoot{} \newenvironment{CompactList} {\begin{list}{}{ \setlength{\leftmargin}{0.5cm} \setlength{\itemsep}{0pt} \setlength{\parsep}{0pt} \setlength{\topsep}{0pt} \renewcommand{\makelabel}{}}} {\end{list}} \newenvironment{CompactItemize} { \begin{itemize} \setlength{\itemsep}{-3pt} \setlength{\parsep}{0pt} \setlength{\topsep}{0pt} \setlength{\partopsep}{0pt} } {\end{itemize}} \newcommand{\PBS}[1]{\let\temp=\\#1\let\\=\temp} \newlength{\tmplength} \newenvironment{TabularC}[1] { \setlength{\tmplength} {\linewidth/(#1)-\tabcolsep*2-\arrayrulewidth*(#1+1)/(#1)} \par\begin{tabular*}{\linewidth} {*{#1}{|>{\PBS\raggedright\hspace{0pt}}p{\the\tmplength}}|} } {\end{tabular*}\par} \newcommand{\entrylabel}[1]{ {\parbox[b]{\labelwidth-4pt}{\makebox[0pt][l]{\textbf{#1}}\\}}} \newenvironment{Desc} {\begin{list}{} { \settowidth{\labelwidth}{40pt} \setlength{\leftmargin}{\labelwidth} \setlength{\parsep}{0pt} \setlength{\itemsep}{-4pt} \renewcommand{\makelabel}{\entrylabel} } } {\end{list}} \newenvironment{Indent} {\begin{list}{}{\setlength{\leftmargin}{0.5cm}} \item[]\ignorespaces} {\unskip\end{list}} \setlength{\parindent}{0cm} \setlength{\parskip}{0.2cm} \addtocounter{secnumdepth}{1} \sloppy \usepackage[T1]{fontenc} libspe-1.2.2/doc/DoxyfileRef0000640000076400007640000013524110533602312015473 0ustar cellbldcellbld# Doxyfile 1.3.9.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = libspe # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = 1.2 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of source # files, where putting all generated files in the same directory would otherwise # cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, # Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, # Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, # Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, # Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # This tag can be used to specify the encoding used in the generated output. # The encoding is not always determined by the language that is chosen, # but also whether or not the output is meant for Windows or non-Windows users. # In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES # forces the Windows encoding (this is the default for the Windows binary), # whereas setting the tag to NO uses a Unix-style encoding (the default for # all platforms other than Windows). USE_WINDOWS_ENCODING = NO # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = NO # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is used # as the annotated text. Otherwise, the brief description is used as-is. If left # blank, the following values are used ("$name" is automatically replaced with the # name of the entity): "The $name class" "The $name widget" "The $name file" # "is" "provides" "specifies" "contains" "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited # members of a class in the documentation of that class as if those members were # ordinary class members. Constructors, destructors and assignment operators of # the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like the Qt-style comments (thus requiring an # explicit @brief command for a brief description. JAVADOC_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. # If set to NO, the detailed description appears after the member # documentation. DETAILS_AT_TOP = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources # only. Doxygen will then generate output that is more tailored for Java. # For instance, namespaces will be presented as packages, qualified scopes # will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = YES # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = YES # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = YES # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = YES # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = YES # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = YES # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = YES # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = NO # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = NO # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. SHOW_DIRECTORIES = NO #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = libspe.h #INPUT = doc/design.txt spebase speevent spethread spegang # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp # *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories # that are symbolic links (a Unix filesystem feature) are excluded from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. EXCLUDE_PATTERNS = default* # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = $(HOME)/workspace/head-libspe2/tests # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = $(HOME) # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = NO #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = NO # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = YES # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = doc/LatexHeader # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = YES #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = YES # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_PREDEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse the # parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or # super classes. Setting the tag to NO turns the diagrams off. Note that this # option is superseded by the HAVE_DOT option below. This is only a fallback. It is # recommended to install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = YES # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will # generate a call dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected # functions only using the \callgraph command. CALL_GRAPH = YES # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found on the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_WIDTH = 1024 # The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_HEIGHT = 1024 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes that # lay further from the root node will be omitted. Note that setting this option to # 1 or 2 may greatly reduce the computation time needed for large code bases. Also # note that a graph may be further truncated if the graph's image dimensions are # not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). # If 0 is used for the depth value (the default), the graph is not depth-constrained. MAX_DOT_GRAPH_DEPTH = 0 # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO libspe-1.2.2/elf_loader.c0000640000076400007640000001642210533602310015020 0ustar cellbldcellbld/* libspe - A wrapper library to adapt the JSRE SPE usage model to SPUFS * Copyright (C) 2005 IBM Corp. * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include "elf_loader.h" #include "libspe.h" extern int __env_spu_debug_start; extern int __env_spu_info; static void display_debug_output(Elf32_Ehdr *elf_start, Elf32_Shdr *sh); #define __PRINTF(fmt, args...) { fprintf(stderr,fmt , ## args); } #ifdef DEBUG #define DEBUG_PRINTF(fmt, args...) __PRINTF(fmt , ## args) #define TAG DEBUG_PRINTF("TAG: %d@%s\n", __LINE__, __FILE__); #else #define DEBUG_PRINTF(fmt, args...) #define TAG #endif static const unsigned char expected[EI_PAD] = { [EI_MAG0] = ELFMAG0, [EI_MAG1] = ELFMAG1, [EI_MAG2] = ELFMAG2, [EI_MAG3] = ELFMAG3, [EI_CLASS] = ELFCLASS32, [EI_DATA] = ELFDATA2MSB, [EI_VERSION] = EV_CURRENT, [EI_OSABI] = ELFOSABI_SYSV, [EI_ABIVERSION] = 0 }; int check_spe_elf(Elf32_Ehdr *ehdr) { /* Validate ELF */ if (memcmp(ehdr->e_ident, expected, EI_PAD) != 0) { DEBUG_PRINTF("invalid ELF header.\n"); DEBUG_PRINTF("expected 0x%016llX != 0x%016llX\n", *(long long *) expected, *(long long *) (ehdr->e_ident)); errno = EINVAL; return -errno; } /* Validate the machine type */ if (ehdr->e_machine != 0x17) { DEBUG_PRINTF("not an SPE ELF object"); errno = EINVAL; return -errno; } /* Validate ELF object type. */ if (ehdr->e_type != ET_EXEC) { DEBUG_PRINTF("invalid SPE ELF type.\n"); DEBUG_PRINTF("SPE type %d != %d\n", ehdr->e_type, ET_EXEC); errno = EINVAL; DEBUG_PRINTF("parse_spu_elf(): errno=%d.\n", errno); return -errno; } return 0; } int verify_spe_elf_image(spe_program_handle_t *handle) { Elf32_Ehdr *ehdr; void *elf_start; elf_start = handle->elf_image; ehdr = (Elf32_Ehdr *)(handle->elf_image); return check_spe_elf(ehdr); } int spe_parse_isolated_elf(spe_program_handle_t *handle, uint64_t *addr, uint32_t *size) { Elf32_Ehdr *ehdr = (Elf32_Ehdr *)handle->elf_image; Elf32_Phdr *phdr; if (ehdr->e_phentsize != sizeof(*phdr)) { DEBUG_PRINTF("Invalid program header format (phdr size=%d)\n", ehdr->e_phentsize); errno = EINVAL; return -errno; } if (ehdr->e_phnum != 1) { DEBUG_PRINTF("Invalid program header count (%d), expected 1\n", ehdr->e_phnum); errno = EINVAL; return -errno; } phdr = (Elf32_Phdr *)(handle->elf_image + ehdr->e_phoff); if (phdr->p_type != PT_LOAD || phdr->p_memsz == 0) { DEBUG_PRINTF("SPE program segment is not loadable (type=%x)\n", phdr->p_type); errno = EINVAL; return -errno; } if (addr) *addr = (uint64_t)(unsigned long) (handle->elf_image + phdr->p_offset); if (size) *size = phdr->p_memsz; return 0; } static int overlay(Elf32_Phdr *ph, Elf32_Phdr *prev_ph) { /* * If our ph segment virtual address fits within that of the * previous ph, this is an overlay. */ if (prev_ph && (ph->p_vaddr >= prev_ph->p_vaddr) && (ph->p_vaddr < (prev_ph->p_vaddr + prev_ph->p_memsz))) return 1; else return 0; } static void copy_to_ld_buffer(spe_program_handle_t *handle, void *buffer, Elf32_Phdr *ph, Elf32_Off toe_offset, long toe_size) { void *start = handle->elf_image; DEBUG_PRINTF("SPE_LOAD %p (0x%x) -> %p (0x%x) (%i bytes)\n", buffer + ph->p_vaddr, ph->p_vaddr, start + ph->p_offset, ph->p_offset, ph->p_filesz); /* toe segment comes from the shadow */ if (ph->p_offset == toe_offset) { /* still makes a copy if toe is buried with other * sections */ if (toe_size != ph->p_filesz && ph->p_filesz) { DEBUG_PRINTF("loading base copy\n"); memcpy(buffer + ph->p_vaddr, start + ph->p_offset, ph->p_filesz); } /* overlay only the total toe section size */ DEBUG_PRINTF("loading toe %X %X\n", ph->p_offset, toe_offset); memcpy(buffer + ph->p_vaddr, handle->toe_shadow, toe_size); } else if (ph->p_filesz) { memcpy(buffer + ph->p_vaddr, start + ph->p_offset, ph->p_filesz); } DEBUG_PRINTF("done ...\n"); } int load_spe_elf (spe_program_handle_t *handle, void *ld_buffer, struct spe_ld_info *ld_info) { Elf32_Ehdr *ehdr; Elf32_Phdr *phdr; Elf32_Phdr *ph, *prev_ph; Elf32_Shdr *shdr; Elf32_Shdr *sh; Elf32_Off toe_offset = 0; long toe_size = 0; char* str_table = 0; int num_load_seg = 0; void *elf_start; int ret; DEBUG_PRINTF("load_spe_elf(%p, %p)\n", handle, ld_buffer); elf_start = handle->elf_image; DEBUG_PRINTF("load_spe_elf(%p, %p)\n", handle->elf_image, ld_buffer); ehdr = (Elf32_Ehdr *)(handle->elf_image); /* Check for a Valid SPE ELF Image (again) */ if ((ret = check_spe_elf(ehdr))) return ret; /* Start processing headers */ phdr = (Elf32_Phdr *) ((char *) ehdr + ehdr->e_phoff); shdr = (Elf32_Shdr *) ((char *) ehdr + ehdr->e_shoff); str_table = (char*)ehdr + shdr[ehdr->e_shstrndx].sh_offset; /* traverse the sections to locate the toe segment */ /* by specification, the toe sections are grouped together in a segment */ for (sh = shdr; sh < &shdr[ehdr->e_shnum]; ++sh) { DEBUG_PRINTF("section name: %s\n", str_table+sh->sh_name); if (strcmp(".toe", str_table+sh->sh_name) == 0) { DEBUG_PRINTF("section offset: %d\n", sh->sh_offset); toe_size += sh->sh_size; if ((toe_offset == 0) || (toe_offset > sh->sh_offset)) toe_offset = sh->sh_offset; } if (strcmp(".note.spu_name", str_table+sh->sh_name) == 0) if (__env_spu_debug_start || __env_spu_info) display_debug_output(elf_start, sh); } /* * Load all PT_LOAD segments onto the SPE local store buffer. */ DEBUG_PRINTF("Segments: 0x%x\n", ehdr->e_phnum); for (ph = phdr, prev_ph = NULL; ph < &phdr[ehdr->e_phnum]; ++ph) { switch (ph->p_type) { case PT_LOAD: if (!overlay(ph, prev_ph)) { copy_to_ld_buffer(handle, ld_buffer, ph, toe_offset, toe_size); num_load_seg++; } break; case PT_NOTE: DEBUG_PRINTF("SPE_LOAD found PT_NOTE\n"); break; } prev_ph = ph; } if (num_load_seg == 0) { DEBUG_PRINTF("no segments to load"); errno = EINVAL; return -errno; } /* Remember where the code wants to be started */ ld_info->entry = ehdr->e_entry; DEBUG_PRINTF("entry = 0x%x\n", ehdr->e_entry); return 0; } static void display_debug_output(Elf32_Ehdr *elf_start, Elf32_Shdr *sh) { typedef struct { unsigned long namesz; unsigned long descsz; unsigned long type; char name[8]; char lookupname[32]; } ELF_NOTE; ELF_NOTE *note = (ELF_NOTE *)((void *)elf_start+sh->sh_offset); printf("Loading SPE program : %s\n", note->lookupname); printf("SPU LS Entry Addr : 0x%05x\n", elf_start->e_entry); } libspe-1.2.2/elf_loader.h0000640000076400007640000000301510533602310015017 0ustar cellbldcellbld/* * libspe - A wrapper library to adapt the JSRE SPE usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "libspe.h" #include "spe.h" #define LS_SIZE 0x40000 /* 256K (in bytes) */ #define SPE_LDR_PROG_start (LS_SIZE - 512) // location of spe_ld.so prog #define SPE_LDR_PARAMS_start (LS_SIZE - 128) // location of spe_ldr_params typedef union { unsigned long long ull; unsigned int ui[2]; } addr64; struct spe_ld_info { unsigned int entry; }; /* * Global API : */ int check_spe_elf(Elf32_Ehdr *ehdr); int verify_spe_elf_image(spe_program_handle_t *handle); int load_spe_elf (spe_program_handle_t *handle, void *ld_buffer, struct spe_ld_info *ld_info); int spe_parse_isolated_elf(spe_program_handle_t *handle, uint64_t *addr, uint32_t *size); libspe-1.2.2/elfspe-unregister0000750000076400007640000000006110533602311016141 0ustar cellbldcellbld#!/bin/sh echo -1 > /proc/sys/fs/binfmt_misc/spe libspe-1.2.2/elfspe.c0000640000076400007640000001065310533602310014202 0ustar cellbldcellbld/* * elfspe - A wrapper to allow direct execution of SPE binaries * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define _XOPEN_SOURCE 600 #include #include #include #include #include "libspe.h" #include "spe.h" static void *spe = NULL; #ifndef LS_SIZE #define LS_SIZE 0x40000 /* 256K (in bytes) */ #define LS_ADDR_MASK (LS_SIZE - 1) #endif /* LS_SIZE */ static void handler (int signr ) __attribute__ ((noreturn)); static void handler (int signr) { if (spe) spe_cleanup (spe); fprintf (stderr, "Killed by signal %d\n", signr); exit (128 + signr); } struct spe_regs { unsigned int r3[4]; unsigned int r4[4]; unsigned int r5[4]; }; /* spe_copy_argv - setup C99-style argv[] region for SPE main(). * * Duplicate command line arguments and set up argv pointers * to be absolute LS offsets, allowing SPE program to directly * reference these strings from its own LS. * * An SPE entry function (crt0.o) can take the data from spe_regs * and copy the argv region from EA to the top of LS (largest addr), * and set $SP per ABI requirements. Currently, this looks something * like: * * +-----+ 0 * | txt | * |-----| * | | * | ^ | * | | | * | | | * |stack| * |-----| ls_dst (LS_SIZE-nbytes) * | args| * +-----+ LS_SIZE */ static int spe_copy_argv(int argc, char **argv, struct spe_regs *ret) { unsigned int *argv_offsets; void *start = NULL; char *ptr, *end; union { unsigned long long ull; unsigned int ui[2]; } addr64; int spe_arg_max = 4096; int i, nbytes = 0; memset(ret, 0, sizeof(struct spe_regs)); if ((argc <= 0) || getenv("SPE_NO_ARGS")) { return 0; } if (getenv("SPE_ARG_MAX")) { int v; v = strtol((const char *) getenv("SPE_ARG_MAX"), (char **) NULL, 0); if ((v >= 0) && (v <= spe_arg_max)) spe_arg_max = v & ~(15); } for (i = 0; i < argc; i++) { nbytes += strlen(argv[i]) + 1; } nbytes += (argc * sizeof(unsigned int)); nbytes = (nbytes + 15) & ~(15); if (nbytes > spe_arg_max) { return 2; } posix_memalign(&start, 16, nbytes); if (!start) { return 3; } addr64.ull = (unsigned long long) ((unsigned long) start); memset(start, 0, nbytes); ptr = (char *)start; end = (char *)start + nbytes; argv_offsets = (unsigned int *) ptr; ptr += (argc * sizeof(unsigned int)); for (i = 0; i < argc; i++) { int len = strlen(argv[i]) + 1; argv_offsets[i] = LS_SIZE - ((unsigned int) (end - ptr)); argv_offsets[i] &= LS_ADDR_MASK; memcpy(ptr, argv[i], len); ptr += len; } ret->r3[0] = argc; ret->r4[0] = LS_SIZE - nbytes; ret->r4[1] = addr64.ui[0]; ret->r4[2] = addr64.ui[1]; ret->r4[3] = nbytes; return 0; } int main (int argc, char **argv) { spe_gid_t gid; struct spe_regs params; int rc; spe_program_handle_t *spe_handle; signal (SIGSEGV, handler); signal (SIGBUS, handler); signal (SIGILL, handler); signal (SIGFPE, handler); signal (SIGTERM, handler); signal (SIGHUP, handler); signal (SIGINT, handler); if (argc < 2) { fprintf (stderr, "Usage: elfspe [spe-elf]\n"); exit (1); } spe_handle = spe_open_image (argv[1]); if (!spe_handle) { perror (argv[1]); exit (1); } if (spe_copy_argv(argc-1, &argv[1], ¶ms)) { perror ("spe_copy_argv"); exit (1); } gid = spe_create_group(0,0,0); if (!gid) { perror ("create_group"); exit (1); } spe = spe_setup (gid, spe_handle, ¶ms, NULL, SPE_USER_REGS); if (!spe) { perror ("spe_setup"); exit (1); } rc = do_spe_run (spe); spe_cleanup (spe); return rc & 0xff; } libspe-1.2.2/handler.c0000640000076400007640000000125010533602310014332 0ustar cellbldcellbld#include #include #include /* !!!! remove for drop to barcelona */ /* TODO: implement a list. for now one handler is enough */ int handler_append (handler_t * ph, int (*handler) (unsigned long *, unsigned long)) { ph->handler = handler; return (0); } int handler_run (handler_t * ph, unsigned long *mapbase, unsigned long args) { if (ph->handler) { ph->handler (mapbase, args); } return (0); } handler_t * handler_new (char *pathname) { handler_t *ph; ph = (handler_t *) malloc (sizeof (handler_t)); handler_append( ph, default_syscall_handler ); /* !!!! remove for drop to barcelona */ return (ph); } libspe-1.2.2/handler.h0000640000076400007640000000054610533602310014346 0ustar cellbldcellbld#ifndef __HANDLER_H #define __HANDLER_H typedef struct { char *pathname; int (*handler) (unsigned long *, unsigned long); } handler_t; int handler_append (handler_t * ph, int (*handler) (unsigned long *, unsigned long)); int handler_run (handler_t * ph, unsigned long *mapbase, unsigned long args); handler_t *handler_new (char *pathname); #endif libspe-1.2.2/handler_utils.h0000640000076400007640000000547110533602311015571 0ustar cellbldcellbld/* handler_utils.h - definitions for assisted SPE library calls. * * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __HANDLER_UTILS_H__ #define __HANDLER_UTILS_H__ struct spe_reg128 { unsigned int slot[4]; }; #ifndef LS_SIZE #define LS_SIZE 0x40000 /* 256K (in bytes) */ #define LS_ADDR_MASK (LS_SIZE - 1) #endif /* LS_SIZE */ #define __PRINTF(fmt, args...) { fprintf(stderr,fmt , ## args); } #ifdef DEBUG #define DEBUG_PRINTF(fmt, args...) __PRINTF(fmt , ## args) #else #define DEBUG_PRINTF(fmt, args...) #endif #define LS_ARG_ADDR(_index) \ (&((struct spe_reg128 *) ((char *) ls + ls_args))[_index]) #define DECL_RET() \ struct spe_reg128 *ret = LS_ARG_ADDR(0) #define GET_LS_PTR(_off) \ (void *) ((char *) ls + ((_off) & LS_ADDR_MASK)) #define DECL_0_ARGS() \ unsigned int ls_args = (opdata & 0xffffff) #define DECL_1_ARGS() \ DECL_0_ARGS(); \ struct spe_reg128 *arg0 = LS_ARG_ADDR(0) #define DECL_2_ARGS() \ DECL_1_ARGS(); \ struct spe_reg128 *arg1 = LS_ARG_ADDR(1) #define DECL_3_ARGS() \ DECL_2_ARGS(); \ struct spe_reg128 *arg2 = LS_ARG_ADDR(2) #define DECL_4_ARGS() \ DECL_3_ARGS(); \ struct spe_reg128 *arg3 = LS_ARG_ADDR(3) #define DECL_5_ARGS() \ DECL_4_ARGS(); \ struct spe_reg128 *arg4 = LS_ARG_ADDR(4) #define DECL_6_ARGS() \ DECL_5_ARGS(); \ struct spe_reg128 *arg5 = LS_ARG_ADDR(5) #define PUT_LS_RC(_a, _b, _c, _d) \ ret->slot[0] = (unsigned int) (_a); \ ret->slot[1] = (unsigned int) (_b); \ ret->slot[2] = (unsigned int) (_c); \ ret->slot[3] = (unsigned int) (_d); \ __asm__ __volatile__ ("sync" : : : "memory") #endif /* __HANDLER_UTILS_H__ */ libspe-1.2.2/include/0000755000076400007640000000000010575455116014222 5ustar cellbldcellbldlibspe-1.2.2/include/sys/0000755000076400007640000000000010575455116015040 5ustar cellbldcellbldlibspe-1.2.2/include/sys/spe.h0000640000076400007640000000114010533602312015752 0ustar cellbldcellbld#ifndef __SYS_SPE_H #define __SYS_SPE_H #include #include #ifndef __NR_spe_run #define __NR_spe_run 278 #endif #ifndef __NR_spe_create #define __NR_spe_create 279 #endif #define SPU_CREATE_EVENTS_ENABLED 0x0001 #define SPU_CREATE_GANG 0x0002 #define SPU_CREATE_NOSCHED 0x0004 #define SPU_CREATE_ISOLATE 0x0008 static inline int spe_run(int fd, unsigned int *npc, unsigned int *status) { return syscall(__NR_spe_run, fd, npc, status); } static inline int spe_create(const char * path, int flags, mode_t mode) { return syscall(__NR_spe_create, path, flags, mode); } #endif libspe-1.2.2/libspe.h0000640000076400007640000013613510533602311014214 0ustar cellbldcellbld/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /** \file * libspe.h contains the public API funtions */ #ifndef _libspe_h_ #define _libspe_h_ #ifdef __cplusplus extern "C" { #endif #include "cbea_map.h" typedef void *speid_t; typedef void *spe_gid_t; /* Flags for spe_create_thread */ #define SPE_USER_REGS 0x0002 /* 128b user data for r3-5. */ #define SPE_CFG_SIGNOTIFY1_OR 0x00000010 #define SPE_CFG_SIGNOTIFY2_OR 0x00000020 #define SPE_MAP_PS 0x00000040 #define SPE_ISOLATE 0x00000080 #define SPE_DEF_GRP 0x00000000 #define MAX_THREADS_PER_GROUP 16 enum ps_area { SPE_MSSYNC_AREA, SPE_MFC_COMMAND_AREA, SPE_CONTROL_AREA, SPE_SIG_NOTIFY_1_AREA, SPE_SIG_NOTIFY_2_AREA }; /** spe user context */ struct spe_ucontext { unsigned int gprs[128][4]; unsigned int fpcr[4]; unsigned int decr; unsigned int decr_status; unsigned int npc; unsigned int tag_mask; unsigned int event_mask; unsigned int srr0; unsigned int _reserved[2]; void * ls; }; /** spe_program_handle per CESOF spec */ typedef struct spe_program_handle { unsigned int handle_size; void *elf_image; void *toe_shadow; } spe_program_handle_t; /* SIGSPE maps to SIGURG */ #define SIGSPE SIGURG /* spe_events */ #define SPE_EVENT_MAILBOX 0x0001 /*Interrupting mailbox data */ #define SPE_EVENT_STOP 0x0002 /*SPE 'stop-and-signal data' */ #define SPE_EVENT_TAG_GROUP 0x0004 /*Tag group complete data */ #define SPE_EVENT_DMA_ALIGNMENT 0x0008 /*A DMA alignment error */ #define SPE_EVENT_SPE_ERROR 0x0010 /*An illegal instruction error*/ #define SPE_EVENT_SPE_DATA_SEGMENT 0x0020 /*A DMA segmentation error */ #define SPE_EVENT_SPE_DATA_STORAGE 0x0040 /*A DMA storage error */ #define SPE_EVENT_SPE_TRAPPED 0x0080 /*SPE 'halt' instruction */ #define SPE_EVENT_THREAD_EXIT 0x0100 /*A thread has exited */ #define SPE_EVENT_ERR 0x0200 /*An error occurred */ #define SPE_EVENT_NVAL 0x0400 /*Invalid request - deprecated*/ #define SPE_EVENT_INVALID_DMA_CMD 0x0800 /*Invalid MFC/DMA command */ struct spe_event { spe_gid_t gid; /* input, SPE group id */ int events; /* input, requested event mask */ int revents; /* output, returned events */ speid_t speid; /* output, returned speid */ unsigned long data; /* output, returned data */ }; /* Signal Targets */ #define SPE_SIG_NOTIFY_REG_1 0x0001 #define SPE_SIG_NOTIFY_REG_2 0x0002 /* APIs for SPE threads. */ /** * The spe_create_group function allocates a new SPE thread group. SPE thread groups * define the scheduling policies and priorities for a set of SPE threads. Each SPE * thread belongs to exactly one group. * As an application creates SPE threads, the new threads are added to the designated * SPE group. However the total number of SPE threads in a group cannot exceed the * group maximum, which is dependent upon scheduling policy, priority, and * availability of system resources. The spe_group_max function returns the maximum * allowable number of SPE threads for a group. * All runnable threads in an SPE group may be gang scheduled for execution. * Gang scheduling permits low-latency interaction among SPE threads in shared-memory * parallel applications. * * @param policy Defines the scheduling class for SPE threads in a group. * Accepted values are: * SCHED_RR which indicates real-time round-robin scheduling. * SCHED_FIFO which indicates real-time FIFO scheduling. * SCHED_OTHER which is used for low priority tasks suitable for filling * otherwise idle SPE cycles. * The real-time scheduling policies SCHED_RR and SCHED_FIFO are available * only to processes with super-user privileges. * * @param priority Defines the SPE group's scheduling priority within the policy class. * For the real-time policies SCHED_RR and SCHED_FIFO, priority is a value in the range * of 1 to 99. For interactive scheduling (SCHED_OTHER) the priority is a value in the * range 0 to 39. The priority for an SPE thread group can be modified with * spe_set_priority, or queried with spe_get_priority. * * @param use_events A non-zero value for this parameter allows the application to * receive events for SPE threads in the group. SPE events are conceptually similar * to Linux signals, but differ as follows: SPE events are queued, ensuring that * if multiple events are generated, each is delivered; SPE events are delivered * in the order received; SPE events have associated data, including the type of * event and the SPE thread id. The spe_get_event function can be called to wait * for SPE events. * * @return On success, a positive non-zero identifier for a new SPE group is returned. * On error, zero is returned and errno is set to indicate the error. * Possible errors include: * @retval ENOMEM The SPE group could not be allocated due to lack of system resources. * @retval ENOMEM The total number of SPE groups in the system has reached the system * maximum value. * @retval EINVAL The requested scheduling policy or priority was invalid. * @retval EPERM The process does not have sufficient privileges to create an SPE * group with the requested scheduling policy or priority. * @retval ENOSYS The SPE group could not be allocated due to lack of implementation * support for the specified scheduling priority or policy. * * @sa spe_create_thread(), spe_group_defaults(), spe_group_max(), spe_get_priority(), * spe_set_priority(), spe_get_policy() * */ extern spe_gid_t spe_create_group (int policy, int priority, int spe_events); /** * The spe_group_max function returns the maximum number of SPE threads that may be * created for an SPE group, as indicated by gid. * The total number of SPE threads in a group cannot exceed the group maximum, * which is dependent upon the group’s scheduling policy, priority, and availability * of system resources. * @param spe_gid This is the identifier of the SPE group. * @return On success, the maximum number of SPE threads allowed for the SPE group * is return. On error, -1 is returned and errno is set appropriately. * Possible errors include: * @retval EPERM The calling process does not have privileges to query the SPE group. * @retval ESRCH The specified SPE group could not be found. * @sa spe_create_group, spe_create_thread */ extern int spe_group_max (spe_gid_t spe_gid); /** * The spe_count_physical_spes returns the total number of physical SPEs available * to applications in the system under control of the currently running OS. * * @return Value On success, the number of physical SPEs is returned. On error, -1 is * returned and errno is set appropriately. * Possible errors include: * @retval EIO An I/O error occurred */ extern int spe_count_physical_spes(void); /** * spe_create_thread creates a new SPE thread of control that can be executed independently of the calling task. As an application creates SPE threads, the threads are added to the designated SPE group. The total number of SPE threads in a group cannot exceed the group maximum. The spe_group_max function returns the number of SPE threads allowed for the group. * @param gid Identifier of the SPE group that the new thread will belong to. SPE group identifiers are returned by spe_create_group. The new SPE thread inherits scheduling attributes from the designated SPE group. If gid is equal to SPE_DEF_GRP (0), then a new group is created with default scheduling attributes, as set by calling spe_group_defaults. * * @param handle * Indicates the program to be executed on the SPE. This is an opaque pointer to an * SPE ELF image which has already been loaded and mapped into system memory. This * pointer is normally provided as a symbol reference to an SPE ELF executable image * which has been embedded into a PPE ELF object and linked with the calling PPE * program. This pointer can also be established dynamically by loading a shared * library containing an embedded SPE ELF executable, using dlopen(2) and dlsym(2), * or by using the spe_open_image function to load and map a raw SPE ELF executable. * @param argp * An (optional) pointer to application specific data, and is passed as the second * parameter to the SPE program. * @param envp * An (optional) pointer to environment specific data, and is passed as the third * parameter to the SPE program. * @param mask * The processor affinity mask for the new thread. Each bit in the mask enables (1) * or disables (0) thread execution on a cpu. At least one bit in the affinity mask * must be enabled. If equal to -1, the new thread can be scheduled for execution * on any processor. The affinity mask for an SPE thread can be changed by calling * spe_set_affinity, or queried by calling spe_get_affinity. * A bit-wise OR of modifiers that are applied when the new thread is created. The * following values are accepted:\n * 0 No modifiers are applied\n * SPE_CFG_SIGNOTIFY1_OR Configure the Signal Notification 1 Register to be in * 'logical OR' mode instead of the default 'Overwrite' mode.\n * SPE_CFG_SIGNOTIFY2_OR Configure the Signal Notification 1 Register to be in * 'logical OR' mode instead of the default 'Overwrite' mode.\n * SPE_MAP_PS Request permission for memory-mapped access to the SPE thread’s * problem state area(s). Direct access to problem state is a real-time feature, * and may only be available to programs running with privileged authority * (or in Linux, to processes with access to CAP_RAW_IO; see capget(2) for details). * * @param flags SPE_USER_REGS * Specifies that the SPE setup registers r3, r4, and r5 are initialized with the 48 bytes pointed to by argp. * * @return * On success, a positive non-zero identifier of the newly created SPE thread is returned. On error, 0 is returned and errno is set to indicate the error. * Possible errors include: * @retval ENOMEM The SPE thread could not be allocated due to lack of system resources * @retval EINVAL The value passed for mask or flags was invalid. * SPE Thread Management Facilities 5 * @retval EPERM The process does not have permission to add threads to the designated SPE group, or to use the SPU_MAP_PS setting. * @retval ESRCH The SPE group could not be found. * @sa spe_create_group * spe_get_group spe_get_ls * spe_get_ps_area * spe_get_threads * spe_group_defaults * spe_group_max * spe_open_image, spe_close_image */ extern speid_t spe_create_thread (spe_gid_t gid, spe_program_handle_t *handle, void *argp, void *envp, unsigned long mask, int flags); /** * spe_recycle */ extern int spe_recycle (speid_t speid, spe_program_handle_t *handle); /** * spe_wait suspends execution of the current process until the SPE thread specified * by speid has exited. If the SPE thread has already exited by the time of the * call (a so-called “zombie” SPE thread), then the function returns immediately. * Any system resources used by the SPE thread are freed. * @param speid Wait for the SPE thread identified. * @param options This parameter is an logical OR of zero or more of the following * constants:\n * WNOHANG Return immediately if the SPE thread has not exited.\n * WUNTRACED Return if the SPE thread is stopped and its status has not been reported. * @param status If this value is non-NULL, spe_wait stores the SPE thread’s exit c * ode at the address indicated by status. This status can be evaluated with the * following macros. Note: these macros take the status buffer, an int, as a * parameter - not a pointer to the buffer!\n * WIFEXITED(status) Is non-zero if the SPE thread exited normally.\n * WEXITSTATUS(status) Evaluates to the least significant eight bits of the return * code of the SPE thread which terminated, which may have been set as the argument * to a call to exit() or as the argument for a return statement in the main program. * This macro can only be evaluated if WIFEXITED returned non-zero.\n * WIFSIGNALED(status) Returns true if the SPE thread exited because of a signal * which was not caught. * WTERMSIG(status) Returns the number of the signal that caused the SPE thread to * terminate. This macro can only be evaluated if WIFSIGNALED returned non-zero. * WIFSTOPPED(status) Returns true if the SPE thread which caused the return is * currently stopped; this is only possible if the call was done using WUNTRACED. * WSTOPSIG(status) Returns the number of the signal which caused the SPE thread * to stop. This macro can only be evaluated if WIFSTOPPED returned non-zero. * @return On success, 0 is returned. A 0 value is returned if WNOHANG was used and * the SPE thread was available. On failure, -1 is returned and errno is set * appropriately. * Possible errors include: * @retval ESRCH The specified SPE thread could not be found. * @retval EINVAL The options parameter is invalid. * @retval EFAULT status points to an address that was not contained in the calling * process’s address space. * @retval EPERM The calling process does not have permission to wait on the * specified SPE thread. * @retval EAGAIN The wait queue was active at the time spe_wait was called, * prohibiting additional waits, so try again. * * @sa spe_create_thread */ extern int spe_wait (speid_t speid, int *status, int options); /** * spe_get_event polls or waits for events that may be generated by threads in an SPE * group. * @param pevents This specifies an array of SPE event structures * @param nevents This specifies the number of spe_event structures in the pevents * array. * @param timeout This specifies the timeout value in milliseconds. A negative value * means an infinite timeout. If none of the events requested (and no error) had * occurred any of the SPE groups, the operating system waits for timeout * milliseconds for one of these events to occur. * * @return On success, a positive number is returned, where the number returned * indicates the number of structures which have non-zero revents fields (in other * words, those with events or errors reported). A value of 0 indicates that the * call timed out and no events have been selected. On error, -1 is returned and * errno is set appropriately.\n * Possible errors include: * @retval EFAULT The array given as a parameter was not contained in the calling * program’s address space. * @retval EINVAL No SPE groups have yet been created. * @retval EINTR A signal occurred before any requested event. * @retval EPERM The current process does not have permission to get SPE events. * * @sa spe_create_group, poll */ extern int spe_get_event(struct spe_event *pevents, int nevents, int timeout); /** * The spe_kill can be used to send a control signal to an SPE thread. * @param speid The signal is delivered to the SPE thread identified. * @param sig This indicates the type of control signal to be delivered. * It may be one of the following values:\n * SIGKILL Kill the specified SPE thread.\n * SIGSTOP Stop execution of the specified SPE thread.\n * SIGCONT Resume execution of the specified SPE thread.\n * * @return On success, 0 is returned. On error, -1 is returned and errno is set * appropriately. * Possible errors include: * @retval ENOSYS The spe_kill operation is not supported by the implementation or * environment. * @retval EPERM The calling process does not have permission to perform the kill * action for the receiving SPE thread. * @retval ESRCH The SPE thread does not exist. Note that a existing SPE thread * might be a zombie, an SPE thread which is already committed termination but * yet had spe_wait called for it. * @sa spe_create_thread, spe_wait, kill (2) */ extern int spe_kill (speid_t speid, int sig); /** * The scheduling priority for the SPE thread group, as indicated by gid, is * obtained by calling the spe_get_priority. * @param gid The identifier of a specific SPE group. * @return On success, spe_get_priority returns a priority value of 0 to 99. On * failure, spe_get_priority returns -1 and sets errno appropriately. * Possible errors include: * @retval ESRCH The specified SPE thread group could not be found. * @sa spe_create_group */ extern int spe_get_priority(spe_gid_t gid); /** * The scheduling priority for the SPE thread group, as indicated by gid is set by * calling the spe_set_priority function. * For the real-time policies SCHED_RR and SCHED_FIFO, priority is a value in the * range of 1 to 99. Only the super-user may modify real-time priorities. * For the interactive policy SCHED_OTHER, priority is a value in the range 0 to 39. * Only the super-user may raise interactive priorities. * * @param gid The identifier of a specific SPE group. * @param priority Specified the SPE thread group’s scheduling priority within the * group’s scheduling policy class. * @return On success, spe_set_priority returns zero. On failure, spe_set_priority * returns -1 and sets errno appropriately. * Possible errors include: * @retval EINVAL The specified priority value is invalid. * @retval EPERM The current process does not have permission to set the specified * SPE thread group priority. * @retval ESRCH The specified SPE thread group could not be found. * @sa spe_create_group */ extern int spe_set_priority(spe_gid_t gid, int priority); /** * The scheduling policy class for an SPE group is queried by calling the * spe_get_policy function. * * @param gid The identifier of a specific SPE group. * @return On success, spe_get_policy returns a scheduling policy class value * of SCHED_RR, SCHED_FIFO, or SCHED_OTHER. On failure, spe_get_policy returns -1 * and sets errno appropriately. * SPE thread group priority. * @retval ESRCH The specified SPE thread group could not be found. * @sa spe_create_group */ extern int spe_get_policy(spe_gid_t gid); /** * The spe_get_group function returns the SPE group identifier for the SPE thread, * as indicated by speid. * @param speid The identifier of a specific SPE thread. * @return The SPE group identifier for an SPE thread, or 0 on failure. * Possible errors include: * @retval ESRCH The specified SPE thread could not be found. * * @sa spe_create_group, spe_get_threads */ extern spe_gid_t spe_get_group (speid_t speid); /** * The spe_get_ls function returns the address of the local storage * for the SPE thread indicated by speid. * * @param speid The identifier of a specific SPE thread. * @return On success, a non-NULL pointer is returned. On failure, NULL is returned * and errno is set appropriately. Possible errors include: * @retval ENOSYS Access to the local store of an SPE thread is not supported by * the operating system. * @retval ESRCH The specified SPE thread could not be found. * @sa spe_create_group, spe_get_ps_area */ extern void *spe_get_ls(speid_t speid); /** * spe_group_defaults changes the application defaults for SPE groups. When an * application calls spe_create_thread and designates an SPE group id equal to * SPE_DEF_GRP (0), then a new group is created and the thread is added to the * new group. The group is created with default settings for memory access * privileges and scheduling attributes. By calling spe_group_defaults, the * application can override the settings for these attributes. * The initial attribute values for SPE group 0 are defined as follows: * the policy is set to SCHED_OTHER; the priority is set to 0; and spe_events are * disabled. * * @param policy This defines the scheduling class. Accepted values are:\n * SCHED_RR which indicates real-time round-robin scheduling.\n * SCHED_FIFO which indicates real-time FIFO scheduling.\n * SCHED_OTHER which is used for low priority tasks suitable * for filling otherwise idle SPE cycles.\n * @param priority This defines the default scheduling priority. For the real-time * policies SCHED_RR and SCHED_FIFO, priority is a value in the range of 1 to 99. * For interactive scheduling * (SCHED_OTHER) the priority is a value in the range 0 to 99. * @param spe_events A non-zero value for this parameter registers the application’s * interest i * void *spe_get_ps_area (speid_t speid, enum ps_area area) * Description * The spe_get_ps_area function returns a pointer to the problem state area * specified by ps_area for the SPE thread indicated by speid. In order to * obtain a problem state area pointer the specified SPE thread must have been * created with the SPE_MAP_PS flag set with sufficient privileges. * The problem state pointer can be used to directly access problem state * features without having to make library system calls. Problem state features * include multi-source synchronization, proxy DMAs, mailboxes, and signal notifiers. * In addition, these pointers, along with local store pointers (see spe_get_ls), * can be used to perform SPE to SPE communications via mailboxes, DMA’s and signal * notification. * * @param speid The identifier of a specific SPE thread. * * @param area The problem state area pointer to be granted access and returned. * Possible problem state areas include:\n * - SPE_MSSYNC_AREA Return a pointer to the specified SPE’s MFC multisource * synchronization register problem state area as defined by the following structure: * typedef struct spe_mssync_area {\n * unsigned int MFC_MSSync;\n * } spe_mssync_area_t;\n * \n * - SPE_MFC_COMMAND_AREA Return a pointer to the specified SPE’s MFC command parameter * and command queue control area as defined by the following structure:\n * typedef struct spe_mfc_command_area {\n * unsigned char reserved_0_3[4];\n * unsigned int MFC_LSA;\n * unsigned int MFC_EAH;\n * unsigned int MFC_EAL;\n * unsigned int MFC_Size_Tag;\n * union {\n * unsigned int MFC_ClassID_CMD;\n * unsigned int MFC_CMDStatus;\n * };\n * unsigned char reserved_18_103[236];\n * unsigned int MFC_QStatus;\n * unsigned char reserved_108_203[252];\n * unsigned int Prxy_QueryType;\n * unsigned char reserved_208_21B[20];\n * unsigned int Prxy_QueryMask;\n * unsigned char reserved_220_22B[12];\n * unsigned int Prxy_TagStatus;\n * } spe_mfc_command_area_t;\n * \n * Note: The MFC_EAH and MFC_EAL registers can be simultaneously written using a 64-bit * store. Likewise, MFC_Size_Tag and MFC_ClassID_CMD registers can be simultaneously * written using a 64-bit store. * - SPE_CONTROL_AREA Return a pointer to the specified SPE’s SPU control area as * defined by the following structure:\n * typedef struct spe_spu_control_area {\n * unsigned char reserved_0_3[4];\n * unsigned int SPU_Out_Mbox;\n * unsigned char reserved_8_B[4];\n * unsigned int SPU_In_Mbox;\n * unsigned char reserved_10_13[4];\n * unsigned int SPU_Mbox_Stat;\n * unsigned char reserved_18_1B[4];\n * unsigned int SPU_RunCntl;\n * unsigned char reserved_20_23[4];\n * unsigned int SPU_Status;\n * unsigned char reserved_28_33[12];\n * unsigned int SPU_NPC;\n * } spe_spu_control_area_t;\n * Note: Explicit programmer manipulation of the SPU run control is highly discouraged. * \n * - SPE_SIG_NOTIFY_1_AREA Return a pointer to the specified SPE’s signal * notification area 1 as defined by the following structure: * \n * typedef struct spe_sig_notify_1_area {\n * unsigned char reserved_0_B[12];\n * unsigned int SPU_Sig_Notify_1;\n * } spe_sig_notify_1_area_t;\n * \n * - SPE_SIG_NOTIFY_2_AREA Return a pointer to the specified SPE’s signal notification * area 2 as defined by the following structure: * typedef struct spe_sig_notify_2_area {\n * unsigned char reserved_0_B[12];\n * unsigned int SPU_Sig_Notify_2;\n * } spe_sig_notify_2_area_t;\n * \n * * @return On success, a non-NULL pointer to the requested problem state area * is returned. On failure, NULL is returned and errno is set appropriately. * * @retval EACCES Permission for direct access to the specified problem state * area is denied or the SPE thread was not created with memory-mapped problem * state access. * @retval EINVAL The specified problem state area is invalid. * @retval ENOSYS Access to the specified problem area for the specified SPE * thread is not supported by the operating system. * @retval ESRCH The specified SPE thread could not be found. * @retval EIO I/O error * * @sa spe_create_thread, spe_get_ls */ extern void *spe_get_ps_area (speid_t speid, enum ps_area area); /** * The spe_set_app_data function associates application specific data with an * SPE thread. Any association with previously associated data is lost on success. * On failure, any previous association is unchanged. * * @param speid The identifier of the SPE thread. * * @param data Application specific data to associate with the SPE thread. * * @return On success, spe_set_app_data and spe_get_app_data return 0. On failure, * -1 is returned and errno is set appropriately. * Possible errors include: * @retval EFAULT The address of p_data was invalid. * @retval ESRCH The specified SPE thread could not be found. */ extern int spe_set_app_data( speid_t speid, void* data); /** * The spe_get_app_data function returns the application specific data associated * with the specified SPE thread as set by spe_set_app_data. If no application * data has been associated with the specified thread, then the memory pointed to * by p_data is set to NULL. * * @param speid The identifier of the SPE thread. * * @param p_data A pointer to memory to receive the associated data. * * @return On success, spe_set_app_data and spe_get_app_data return 0. On failure, * -1 is returned and errno is set appropriately. * Possible errors include: * @retval EFAULT The address of p_data was invalid. * @retval ESRCH The specified SPE thread could not be found. */ extern int spe_get_app_data( speid_t speid, void** p_data); /* INOFFICIAL FUNCTION: __spe_get_context_fd(speid) * * returns the file descriptor for the spe context. */ extern int __spe_get_context_fd(speid_t speid); #ifdef __cplusplus } #endif #endif libspe-1.2.2/libspe.spec0000644000076400007640000000614310575455131014732 0ustar cellbldcellbld%define release be0710.1.20070313 Name: libspe Version: 1.2.2 Release: %{release} License: LGPL Group: System Environment/Base URL: http://www.bsc.es/projects/deepcomputing/linuxoncell Source: http://www.bsc.es/projects/deepcomputing/linuxoncell/development/release2.0/libspe/%{name}-%{version}.tar.gz Buildroot: %{_tmppath}/libspe Exclusivearch: ppc ppc64 noarch Summary: SPE Runtime Management Library %ifarch noarch %define sysroot %{nil} %define set_optflags %{nil} %else %define sysroot %{nil} %define set_optflags OPTFLAGS="%{optflags}" %endif %ifarch ppc %define _libdir /usr/lib %endif %ifarch ppc64 %define _libdir /usr/lib64 %endif %define _includedir2 /usr/spu/include %define _initdir /etc/init.d %define _unpackaged_files_terminate_build 0 %package devel Summary: SPE Runtime Management Library Group: Development/Libraries Requires: %{name} = %{version} %ifarch ppcnone %package -n elfspe Summary: Helper for standalong SPE applications Group: Applications/System Requires: %{name} = %{version} %endif %description SPE Runtime Management Library for the Cell Broadband Engine Architecture. %description devel Header and object files for SPE Runtime Management Library. %ifarch ppcnone %description -n elfspe This tool acts as a standalone loader for spe binaries. %endif %prep %setup %build make SYSROOT=%{sysroot} %{set_optflags} prefix=%{_prefix} libdir=%{_libdir} %install rm -rf $RPM_BUILD_ROOT%{sysroot} make install DESTDIR=$RPM_BUILD_ROOT SYSROOT=%{sysroot} prefix=%{_prefix} libdir=%{_libdir} %ifarch ppcnone mkdir -p $RPM_BUILD_ROOT%{sysroot}%{_initdir} cat > $RPM_BUILD_ROOT%{sysroot}%{_initdir}/elfspe <<"EOF" #!/bin/bash # # /etc/rc.d/init.d/elfspe # # registers elfspe handler # # chkconfig: 345 1 1 # description: executes elfspe-register # Source function library. . /etc/init.d/functions start() { echo -n "Starting elfspe: " sh /usr/bin/elfspe-register return 0 } stop() { echo -n "Shutting down elfspe: " sh /usr/bin/elfspe-unregister return 0 } case "$1" in start) start ;; stop) stop ;; status) ;; restart) stop start ;; reload) ;; condrestart) [ -f /var/lock/subsys/elspe ] && restart || : ;; *) echo "Usage: elfspe {start|stop|status|reload|restart" exit 1 ;; esac exit $? EOF chmod +x $RPM_BUILD_ROOT%{sysroot}%{_initdir}/elfspe %endif %clean rm -rf $RPM_BUILD_ROOT %post -p /sbin/ldconfig %postun -p /sbin/ldconfig %ifarch ppcnone %preun -n elfspe [ -f %{_initdir}/elfspe ] && /sbin/chkconfig --del elfspe %post -n elfspe [ -f %{_initdir}/elfspe ] && /sbin/chkconfig --add elfspe [ -f %{_bindir}/elfspe-register ] && %{_bindir}/elfspe-register %endif %files %defattr(-,root,root) %{sysroot}%{_libdir}/*.so.* %files devel %defattr(-,root,root) %{sysroot}%{_libdir}/*.so %{sysroot}%{_libdir}/*.a %{sysroot}%{_includedir}/*.h %{sysroot}%{_includedir2}/*.h %ifarch ppcnone %files -n elfspe %defattr(-,root,root) %{sysroot}%{_bindir}/elfspe-register %{sysroot}%{_bindir}/elfspe-unregister %{sysroot}%{_bindir}/elfspe %{sysroot}/etc/init.d/elfspe %endif %changelog * Thu Nov 24 2005 - Arnd Bergmann 1.0.1-3 - initial spec file for fc5 libspe-1.2.2/ps.c0000640000076400007640000001102210533602311013336 0ustar cellbldcellbld/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "spe.h" #define __PRINTF(fmt, args...) { fprintf(stderr,fmt , ## args); } #ifdef DEBUG #define DEBUG_PRINTF(fmt, args...) __PRINTF(fmt , ## args) #else #define DEBUG_PRINTF(fmt, args...) #endif /* Internal function prototypes. only used internaly. */ static void *map_mss_area(speid_t speid) { struct thread_store *spe = speid; if (spe->mss_mmap_base == MAP_FAILED) { spe->mss_mmap_base = do_spe_map_ps_area(spe, 0, spe->fd_mss, 0x1000); } if (spe->mss_mmap_base == MAP_FAILED) { return NULL; } return spe->mss_mmap_base; } static void *map_mfc_area(speid_t speid) { struct thread_store *spe = speid; if (spe->mfc_mmap_base == MAP_FAILED) { spe->mfc_mmap_base = do_spe_map_ps_area(spe, 0x3000, spe->fd_mfc, 0x1000); } if (spe->mfc_mmap_base == MAP_FAILED) { return NULL; } return spe->mfc_mmap_base; } static void *map_cntl_area(speid_t speid) { struct thread_store *spe = speid; if (spe->cntl_mmap_base == MAP_FAILED) { spe->cntl_mmap_base = do_spe_map_ps_area(spe, 0x4000, spe->fd_cntl, 0x1000); } if (spe->cntl_mmap_base == MAP_FAILED) { return NULL; } return spe->cntl_mmap_base; } static void *map_signal1_area(speid_t speid) { struct thread_store *spe = speid; if (spe->signal1_mmap_base == MAP_FAILED) { spe->signal1_mmap_base = do_spe_map_ps_area(spe, 0x14000, spe->fd_sig1, 0x1000); } if (spe->signal1_mmap_base == MAP_FAILED) { return NULL; } return spe->signal1_mmap_base; } static void *map_signal2_area(speid_t speid) { struct thread_store *spe = speid; if (spe->signal2_mmap_base == MAP_FAILED) { spe->signal2_mmap_base = do_spe_map_ps_area(spe, 0x1c000, spe->fd_sig2, 0x1000); } return spe->signal2_mmap_base; } void *spe_get_ps_area(speid_t speid, enum ps_area area) { void *base_addr; struct thread_store *spe = speid; if (!srch_thread(speid)) return NULL; if (!(spe->flags & SPE_MAP_PS)) { errno = EACCES; return NULL; } if ( area == SPE_MSSYNC_AREA ) { base_addr = map_mss_area(speid); if (base_addr == NULL) { perror("spe_map_ps_area: internal error. cant map mss file."); errno = EIO; return NULL; } return base_addr; } else if ( area == SPE_MFC_COMMAND_AREA ) { base_addr = map_mfc_area(speid); if (base_addr == NULL) { perror("spe_map_ps_area: internal error. cant map mfc file."); errno = EIO; return NULL; } return base_addr ; } else if ( area == SPE_CONTROL_AREA ) { base_addr = map_cntl_area(speid); if (base_addr == NULL) { perror("spe_map_ps_area: internal error. cant map control file."); errno = EIO; return NULL; } return base_addr ; } else if ( area == SPE_SIG_NOTIFY_1_AREA ) { base_addr = map_signal1_area(speid); if (base_addr == NULL) { perror("spe_map_ps_area: internal error. cant map signal1 file."); errno = EIO; return NULL; } return base_addr; } else if ( area == SPE_SIG_NOTIFY_2_AREA ) { base_addr = map_signal2_area(speid); if (base_addr == NULL) { perror("spe_map_ps_area: internal error. cant map signal2 file."); errno = EIO; return NULL; } return base_addr; } perror("spe_map_ps_area: Unsupported call of spe_map_ps_area."); errno = EINVAL; return NULL; } libspe-1.2.2/signal.c0000640000076400007640000000403610533602311014200 0ustar cellbldcellbld/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "spe.h" #define __PRINTF(fmt, args...) { fprintf(stderr,fmt , ## args); } #ifdef DEBUG #define DEBUG_PRINTF(fmt, args...) __PRINTF(fmt , ## args) #else #define DEBUG_PRINTF(fmt, args...) #endif #define SPE_SIGNAL_REG 0x0C unsigned int *spe_signal_address(speid_t speid, int signo) { struct thread_store *thread_store = speid; int fd; void **base_addr; off_t offset; if (signo != 1 && signo != 2){ perror("spe_signal_address: only signal 1 and 2 are valid"); errno = EINVAL; return MAP_FAILED; } if (signo == 1){ fd = thread_store->fd_sig1; base_addr = &thread_store->signal1_mmap_base; offset = 0x14000; } else { fd = thread_store->fd_sig2; base_addr = &thread_store->signal2_mmap_base; offset = 0x1c000; } if ( base_addr == MAP_FAILED ){ *base_addr = do_spe_map_ps_area(thread_store, offset, fd, 0x1000); if ( *base_addr == MAP_FAILED ){ perror("spe_signal_address: internal error. cant map signal file."); errno = EIO; return MAP_FAILED; } } return (*base_addr)+0x0C; } libspe-1.2.2/spe.c0000640000076400007640000007366510535563217013545 0ustar cellbldcellbld /* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "libspe.h" #include "spe.h" #include "elf_loader.h" #include "spe_exec.h" #include "default_c99_handler.h" #include "default_posix1_handler.h" /* * Helpers * * */ int __env_spu_debug_start = 0; int __env_spu_info = 0; int check_env = 1; extern int default_priority; extern int default_policy; extern int default_eventmask; /*Default SPE library call handlers for 21xx stop-and-signal. */ static void *handlers[] = { default_c99_handler, default_posix1_handler, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL }; /* * Context update notification function for debuggers. */ void __spe_context_update_event(void) __attribute__((noinline)); void __spe_context_update_event(void) { /* Prevent function from being marked "pure". */ asm volatile ("" : : : "memory"); } /* * int spe_ldr[]: * SPE code that performs the actual parameter setting: */ static int spe_ldr[] = { 0x30fff203, 0x30fff404, 0x30fff605, 0x30fff806, 0x30fff000, 0x35000000, 0x00000000, 0x00000000 }; void env_check(void) { if (getenv("SPU_DEBUG_START")) __env_spu_debug_start = strtol ((const char *)getenv("SPU_DEBUG_START"),(char **)NULL, 0); if (getenv("SPU_INFO")) __env_spu_info = strtol ((const char *)getenv("SPU_INFO"),(char **)NULL, 0); check_env = 0; } static int spe_open_files(struct thread_store *spe, const char *pathname) { char filename[256]; int ret; /* this one mail fail */ sprintf(filename, "%s/psmap", pathname); spe->fd_psmap = open(filename, O_RDWR); spe->ps_mmap_base=MAP_FAILED; sprintf(filename, "%s/mbox", pathname); spe->fd_mbox = open(filename, O_RDONLY); sprintf(filename, "%s/mbox_stat", pathname); spe->fd_mbox_stat = open(filename, O_RDONLY); sprintf(filename, "%s/ibox", pathname); spe->fd_ibox = open(filename, O_RDONLY); sprintf(filename, "%s/ibox_stat", pathname); spe->fd_ibox_stat = open(filename, O_RDONLY); sprintf(filename, "%s/wbox", pathname); spe->fd_wbox = open(filename, O_WRONLY); sprintf(filename, "%s/wbox_stat", pathname); spe->fd_wbox_stat = open(filename, O_RDONLY); sprintf(filename, "%s/npc", pathname); spe->fd_npc = open(filename, O_RDWR); sprintf(filename, "%s/signal1", pathname); spe->fd_sig1 = open(filename, O_RDWR); spe->signal1_mmap_base=MAP_FAILED; sprintf(filename, "%s/signal2", pathname); spe->fd_sig2 = open(filename, O_RDWR); spe->signal2_mmap_base=MAP_FAILED; /* this one may fail */ sprintf(filename, "%s/mfc", pathname); spe->fd_mfc = open(filename, O_RDWR); spe->mfc_mmap_base=MAP_FAILED; /* this one may fail */ sprintf(filename, "%s/cntl", pathname); spe->fd_cntl = open(filename, O_RDWR); spe->cntl_mmap_base=MAP_FAILED; /* this one may fail */ sprintf(filename, "%s/mss", pathname); spe->fd_mss = open(filename, O_RDWR); spe->mss_mmap_base=MAP_FAILED; ret=pipe(spe->ev_pipe); if (ret) spe->ev_pipe[0] = spe->ev_pipe[1] = -1; if (spe->fd_mbox < 0 || spe->fd_ibox < 0 || spe->fd_wbox < 0 || spe->fd_mbox_stat < 0 || spe->fd_ibox_stat < 0 || spe->fd_wbox_stat < 0 || spe->fd_npc < 0 || spe->fd_sig1 < 0 || spe->fd_sig2 < 0 || ret ) { DEBUG_PRINTF("Could not open all SPE files.\n"); close(spe->fd_psmap); close(spe->fd_mbox); close(spe->fd_mbox_stat); close(spe->fd_ibox); close(spe->fd_ibox_stat); close(spe->fd_wbox); close(spe->fd_wbox_stat); close(spe->fd_npc); close(spe->fd_sig1); close(spe->fd_sig2); close(spe->fd_mfc); close(spe->fd_cntl); close(spe->fd_mss); close(spe->ev_pipe[0]); close(spe->ev_pipe[1]); return -1; } return 0; } static int spe_setup_mem(struct thread_store *thread_store, void *argp, void *envp) { struct spe_exec_params spe_params __attribute__ ((aligned (4096))); void *spe_ld_buf; struct spe_ld_info ld_info; int rc; addr64 argp64, envp64, tid64; #ifdef SPE_NO_MMAP ssize_t count = 0, num = 0; spe_ld_buf = malloc(LS_SIZE); #else spe_ld_buf = thread_store->mem_mmap_base; #endif memset(spe_ld_buf, 0, LS_SIZE); rc = load_spe_elf (&thread_store->handle, spe_ld_buf, &ld_info); if (rc != 0) { DEBUG_PRINTF ("Load SPE ELF failed..\n"); return rc; } /* Add SPE exec program */ DEBUG_PRINTF ("Add exec prog dst:0x%04x size:0x%04x\n", SPE_LDR_START, sizeof (spe_ldr)); memcpy (spe_ld_buf + SPE_LDR_START, &spe_ldr, sizeof (spe_ldr)); /* Add SPE exec parameters */ spe_params.gpr0[0] = ld_info.entry; spe_params.gpr0[1] = 0; spe_params.gpr0[2] = 0; spe_params.gpr0[3] = 0; argp64.ull = (unsigned long long) (unsigned long) argp; envp64.ull = (unsigned long long) (unsigned long) envp; tid64.ull = (unsigned long long) (unsigned long) thread_store; if (thread_store->flags & SPE_USER_REGS) { /* When flags & SPE_USER_REGS is set, argp points * to an array of 3x128b registers to be passed * directly to the SPE program. */ memcpy(&spe_params.gpr3[0], argp, sizeof(unsigned int) * 12); } else { /* Regular parameter convention for spe_create_thread. */ spe_params.gpr3[0] = tid64.ui[0]; spe_params.gpr3[1] = tid64.ui[1]; spe_params.gpr3[2] = 0; spe_params.gpr3[3] = 0; spe_params.gpr4[0] = argp64.ui[0]; spe_params.gpr4[1] = argp64.ui[1]; spe_params.gpr4[2] = 0; spe_params.gpr4[3] = 0; spe_params.gpr5[0] = envp64.ui[0]; spe_params.gpr5[1] = envp64.ui[1]; spe_params.gpr5[2] = 0; spe_params.gpr5[3] = 0; } spe_params.gpr6[0] = 0; spe_params.gpr6[1] = 0; spe_params.gpr6[2] = 0; spe_params.gpr6[3] = 0; DEBUG_PRINTF ("Add exec param dst:0x%04x size:0x%04x\n", SPE_PARAM_START, sizeof (spe_params)); memcpy (spe_ld_buf + SPE_PARAM_START, &spe_params, sizeof (spe_params)); #ifdef SPE_NO_MMAP /* Copy SPE image to SPUfs */ do { num = write (memfd, spe_ld_buf + count, LS_SIZE - count); if (num == -1) { DEBUG_PRINTF ("Transfer SPE ELF failed..\n"); return -errno; } count += num; } while (count < LS_SIZE && num); close (memfd); /* Free the SPE Buffer */ free (spe_ld_buf); #endif return rc; } /** * Low-level API * */ void * spe_setup (spe_gid_t gid, spe_program_handle_t *handle, void *argp, void *envp, int flags) { struct thread_store *thread_store; int rc, memfd, sigfd; char signame[256], memname[256], pathname[256]; int spe_create_flags; if(!gid) { gid=spe_gid_setup(default_policy,default_priority,default_eventmask); } else { struct group_store *grp = gid; if (grp->numListSize == MAX_THREADS_PER_GROUP) { DEBUG_PRINTF ("Thread group has reached maximum number of members.\n"); errno = ENOMEM; return NULL; } } if (flags & SPE_ISOLATE) flags |= SPE_MAP_PS; /*Allocate thread structure */ thread_store = calloc (1, sizeof *thread_store); if (!thread_store) { DEBUG_PRINTF ("Could not allocate thread store\n"); errno = ENOMEM; return NULL; } thread_store->group_id = gid; thread_store->flags = flags; /* Make the SPU Directory */ sprintf (pathname, "/spu/spethread-%i-%lu", getpid (), (unsigned long)thread_store); DEBUG_PRINTF ("create %s\n", pathname); spe_create_flags = 0; if (flags & SPE_ISOLATE) spe_create_flags = SPU_CREATE_ISOLATE | SPU_CREATE_NOSCHED; if (((struct group_store*)thread_store->group_id)->use_events) spe_create_flags |= SPU_CREATE_EVENTS_ENABLED; rc = spe_create(pathname, spe_create_flags, S_IRUSR | S_IWUSR | S_IXUSR); thread_store->fd_run = rc; if (rc < 0) { DEBUG_PRINTF ("Could not create SPE %s: %s\n", pathname, strerror(errno)); return NULL; } sprintf (memname, "%s/mem", pathname); /* Check SPE */ memfd = open (memname, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); if (memfd < 0) { DEBUG_PRINTF ("Could not open SPE mem file.\n"); return NULL; } /* Prepare Loader */ #ifndef SPE_NO_MMAP thread_store->mem_mmap_base = mmap(0, LS_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, memfd, 0); thread_store->fd_mem = memfd; if (!thread_store->mem_mmap_base) { DEBUG_PRINTF ("Could not allocate SPE memory. \n"); errno = ENOMEM; return NULL; } #endif memcpy(&thread_store->handle, handle, sizeof *handle); if (!(flags & SPE_ISOLATE)) { rc = spe_setup_mem(thread_store, argp, envp); if (rc) { perror("setup mem"); return NULL; } } rc = spe_open_files(thread_store, pathname); if (rc) { perror("open files\n"); return NULL; } rc = add_thread_to_group(gid, thread_store); if ( flags & SPE_CFG_SIGNOTIFY1_OR ) { char one[] = "1"; int ignore; sprintf (signame, "%s/signal1_type", pathname); sigfd = open (signame, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); if (sigfd < 0) { DEBUG_PRINTF ("Could not open SPE signal1_type file.\n"); return NULL; } ignore=write (sigfd, one, 1); close(sigfd); } if ( flags & SPE_CFG_SIGNOTIFY2_OR ) { char one[] = "1"; int ignore; sprintf (signame, "%s/signal2_type", pathname); sigfd = open (signame, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); if (sigfd < 0) { DEBUG_PRINTF ("Could not open SPE signal2_type file.\n"); return NULL; } ignore=write (sigfd, one, 1); close(sigfd); } /* Register SPE image start address as "object-id" for oprofile. */ sprintf (signame, "%s/object-id", pathname); sigfd = open (signame, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); if (sigfd >= 0) { char buf[100]; sprintf (buf, "%p", handle->elf_image); write (sigfd, buf, strlen (buf) + 1); close (sigfd); } __spe_context_update_event(); thread_store->stop = 0; return thread_store; } void spe_cleanup (void *ptr) { struct thread_store *thread_store = ptr; char pathname[256]; sprintf (pathname, "/spu/spethread-%i-%lu", getpid (), (unsigned long)thread_store); close (thread_store->fd_run); close (thread_store->fd_mbox); close (thread_store->fd_mbox_stat); close (thread_store->fd_ibox); close (thread_store->fd_ibox_stat); close (thread_store->fd_wbox); close (thread_store->fd_wbox_stat); close (thread_store->fd_npc); /* If psmap exists, unmap just that, else unmap individual bits */ if (thread_store->fd_psmap < 0) { if (thread_store->signal1_mmap_base != MAP_FAILED) munmap(thread_store->signal1_mmap_base,0x1000); if (thread_store->signal2_mmap_base != MAP_FAILED) munmap(thread_store->signal2_mmap_base,0x1000); if (thread_store->mfc_mmap_base != MAP_FAILED) munmap(thread_store->mfc_mmap_base,0x1000); if (thread_store->cntl_mmap_base != MAP_FAILED) munmap(thread_store->cntl_mmap_base,0x1000); if (thread_store->mss_mmap_base != MAP_FAILED) munmap(thread_store->mss_mmap_base,0x1000); } else { if (thread_store->ps_mmap_base != MAP_FAILED) munmap(thread_store->ps_mmap_base, 0x20000); close (thread_store->fd_psmap); } close (thread_store->fd_mss); close (thread_store->fd_cntl); close (thread_store->fd_mfc); close (thread_store->fd_sig1); close (thread_store->fd_sig2); #ifndef SPE_NO_MMAP munmap(thread_store->mem_mmap_base,LS_SIZE); close (thread_store->fd_mem); #endif close (thread_store->ev_pipe[0]); close (thread_store->ev_pipe[1]); remove_thread_from_group(thread_store->group_id, thread_store); free (thread_store); __spe_context_update_event(); } unsigned int set_npc (void *ptr, unsigned int npc) { struct thread_store *thread_store = ptr; int ret; char npcText[9]; sprintf(npcText,"0x%06x\n",npc); ret = write(thread_store->fd_npc, npcText, 9); if (ret < 0) return -EINVAL; return npc; } static void spe_exit_isolated(struct thread_store *thread) { spe_spu_control_area_t *control_area; control_area = spe_get_ps_area(thread, SPE_CONTROL_AREA); if (!control_area) { DEBUG_PRINTF("%s: could not access SPE control area: %s\n", __FUNCTION__, strerror(errno)); return; } /* 0b10 is an isolated exit request */ control_area->SPU_RunCntl = 0x2; } int do_spe_run (void *ptr) { struct thread_store *thread_store = ptr; int runfd; unsigned int npc; unsigned int code; unsigned int status; unsigned int isolated_ret = 0; npc = SPE_LDR_PROG_start; int ret, rc; DEBUG_PRINTF ("do_spe_run\n"); runfd = thread_store->fd_run; thread_store->thread_status = 1; /* Note: in order to be able to kill a running SPE thread the * spe thread must be cancelable. */ pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL); do { thread_store->thread_status = 2; ret = spe_run(runfd, &npc, &status); code = ret >> 16; DEBUG_PRINTF ("SPE (errno=%d) (npc=0x%06x) (code=0x%08x) (ret=0x%08x) (status=0x%08x).\n", errno, npc, code, ret & 0xffff, status); thread_store->thread_status = 10; //SPE _not_ running. /* If a signal was sent to STOP execution we will pause and wait * for a continue signal before going on. */ if ( thread_store->stop ) { pthread_mutex_lock(&thread_store->event_lock); pthread_cond_init(&thread_store->event_deliver, NULL); thread_store->thread_status = 20; //SPE _pausing_. /* Now wait for the continue signal */ pthread_cond_wait(&thread_store->event_deliver, &thread_store->event_lock); pthread_mutex_unlock(&thread_store->event_lock); thread_store->stop = 0; if (thread_store->killed) // no events when we got killed return -1; thread_store->thread_status = 10; //SPE _not_ running. } if (ret < 0) { if (((struct group_store*)thread_store->group_id)->use_events && errno == EIO) { /* Events are turned on, and this is an event. */ thread_store->event = status; thread_store->ev_data = npc; // //Todo Error handling // write(thread_store->ev_pipe[1], &thread_store->event, 4); } else { DEBUG_PRINTF ("Could not run on SPE: %s.\n", strerror(errno)); return -errno; } } else if (ret & 0x20) { if (((struct group_store*)thread_store->group_id)->use_events ) { /* Events are turned on, and this is an event. */ thread_store->event = SPE_EVENT_SPE_ERROR; thread_store->ev_data = npc; write(thread_store->ev_pipe[1], &thread_store->event, 4); errno = EFAULT; DEBUG_PRINTF ("Returned invalid instruction: %s.\n", strerror(errno)); return -errno; } else { DEBUG_PRINTF ("Could not run on SPE: %s.\n", strerror(errno)); return -errno; } } else if (ret & 0x4) { if (((struct group_store*)thread_store->group_id)->use_events ) { /* Events are turned on, and this is an event. */ thread_store->event = SPE_EVENT_SPE_TRAPPED; thread_store->ev_data = npc; write(thread_store->ev_pipe[1], &thread_store->event, 4); errno = EFAULT; DEBUG_PRINTF ("Returned invalid execution: %s.\n", strerror(errno)); return -errno; } else { DEBUG_PRINTF ("Could not run on SPE: %s.\n", strerror(errno)); return -errno; } } else if (ret & 0x1) { if (((struct group_store*)thread_store->group_id)->use_events ) { /* Events are turned on, and this is an event. */ thread_store->event = status; thread_store->ev_data = npc; write(thread_store->ev_pipe[1], &thread_store->event, 4); errno = EFAULT; DEBUG_PRINTF ("Returned invalid data: %s.\n", strerror(errno)); return -errno; } else { DEBUG_PRINTF ("Could not run on SPE: %s.\n", strerror(errno)); return -errno; } } else if ((ret & 0x6) == 0) { if (((struct group_store*)thread_store->group_id)->use_events ) { /* Events are turned on, and this is an event. */ thread_store->event = status; thread_store->ev_data = npc; write(thread_store->ev_pipe[1], &thread_store->event, 4); errno = EFAULT; DEBUG_PRINTF ("Returned invalid data: %s.\n", strerror(errno)); return -errno; } else { DEBUG_PRINTF ("Could not run on SPE: %s.\n", strerror(errno)); return -errno; } } else if ((code & 0xff00) == 0x2100) { int callnum = code&0xff; DEBUG_PRINTF ("SPE library call: "); if (!handlers[callnum]) { DEBUG_PRINTF ("Unsupported SPE library call signal: 21%i.",callnum); break; } else { int (*handler)(void *, unsigned int); handler=handlers[callnum]; rc = handler(thread_store->mem_mmap_base, npc); if (rc) { DEBUG_PRINTF ("SPE library call unsupported.\n"); thread_store->thread_status = 99; return -ENOSYS; } else { npc += 4; } } } else if (thread_store->flags & SPE_ISOLATE) { if (code == 0) { /* isolated app completed sucessfully, SPE is * back in non-isolated state */ break; } else { /* still in isolated mode (either the load * failed, or the app has exited). Remember the * status code and issue an exit */ isolated_ret = ret; spe_exit_isolated(thread_store); code = 0; } } else if (code < 0x2000) { pthread_mutex_lock(&thread_store->event_lock); pthread_cond_init(&thread_store->event_deliver, NULL); if (((struct group_store*)thread_store->group_id)->use_events) { int callnum = code; // // Event - driven 21xx hanlers // thread_store->event = SPE_EVENT_STOP; thread_store->ev_data = callnum; // //Todo Error handling // write(thread_store->ev_pipe[1], &thread_store->event, 4); //Show that we're waiting thread_store->event_pending = 1; // Wait for a signal. pthread_cond_wait(&thread_store->event_deliver, &thread_store->event_lock); thread_store->event_pending = 0; pthread_mutex_unlock(&thread_store->event_lock); } else { pthread_mutex_unlock(&thread_store->event_lock); DEBUG_PRINTF ("SPE user events not enabled.\n"); thread_store->thread_status = 99; return -ENOSYS; } } } while (((code & 0xff00) == 0x2100 || (code < 0x2000)) && !thread_store->killed ); DEBUG_PRINTF ("SPE thread result: %08x:%04x\n", npc, code); /* Save status & npc */ if (thread_store->flags & SPE_ISOLATE) { code = isolated_ret >> 16; thread_store->ret_status = isolated_ret; thread_store->npc = 0; } else { thread_store->ret_status = ret; thread_store->npc = npc; } // //Event code // if (((struct group_store*)thread_store->group_id)->use_events) { thread_store->event = SPE_EVENT_THREAD_EXIT; thread_store->ev_data = code & 0xff; // //Todo Error handling // write(thread_store->ev_pipe[1], &thread_store->event, 4); } thread_store->thread_status = 99; return code; } static int toe_check_syms(Elf32_Ehdr *ehdr, Elf32_Shdr *sh) { Elf32_Sym *sym, *sym_hdr, *sym_end; Elf32_Shdr *shdr; char *str_table; char *sym_name; int ret; shdr = (Elf32_Shdr*) ((char*) ehdr + ehdr->e_shoff); sym_hdr = (Elf32_Sym*) ((char*) ehdr + sh->sh_offset); sym_end = (Elf32_Sym*) ((char*) ehdr + sh->sh_offset + sh->sh_size); str_table = (char*)ehdr + shdr[sh->sh_link].sh_offset; ret = 0; for (sym = sym_hdr; sym < sym_end; sym++) if (sym->st_name) { sym_name = str_table + sym->st_name; if ((strncmp(sym_name, "_EAR_", 5) == 0) && (strcmp(sym_name, "_EAR_") != 0)) { /* * We have a prefix of _EAR_ followed by * something else. This is not currently * (and might not ever be) supported: for * a _EAR_foo, it requires a lookup of foo * in the ppu ELF file. */ fprintf(stderr, "Invalid _EAR_ symbol '%s'\n", sym_name); errno = EINVAL; ret = 1; } } return ret; } static int toe_ear (spe_program_handle_t *speh) { Elf32_Ehdr *ehdr; Elf32_Shdr *shdr, *sh; char *str_table; char **ch; int ret; long toe_size; ehdr = (Elf32_Ehdr*) (speh->elf_image); shdr = (Elf32_Shdr*) ((char*) ehdr + ehdr->e_shoff); str_table = (char*)ehdr + shdr[ehdr->e_shstrndx].sh_offset; toe_size = 0; for (sh = shdr; sh < &shdr[ehdr->e_shnum]; ++sh) if (strcmp(".toe", str_table + sh->sh_name) == 0) toe_size += sh->sh_size; ret = 0; if (toe_size > 0) { for (sh = shdr; sh < &shdr[ehdr->e_shnum]; ++sh) if (sh->sh_type == SHT_SYMTAB || sh->sh_type == SHT_DYNSYM) ret = toe_check_syms(ehdr, sh); if (!ret && toe_size != 16) { /* Paranoia */ fprintf(stderr, "Unexpected toe size of %ld\n", toe_size); errno = EINVAL; ret = 1; } } if (!ret && toe_size) { /* * Allocate toe_shadow, and fill it with elf_image. */ speh->toe_shadow = malloc(toe_size); if (speh->toe_shadow) { ch = (char**) speh->toe_shadow; if (sizeof(char*) == 8) { ch[0] = (char*) speh->elf_image; ch[1] = 0; } else { ch[0] = 0; ch[1] = (char*) speh->elf_image; ch[2] = 0; ch[3] = 0; } } else { errno = ENOMEM; ret = 1; } } return ret; } struct image_handle { spe_program_handle_t speh; unsigned int map_size; }; spe_program_handle_t *spe_open_image(const char *filename) { /* allocate an extra integer in the spe handle to keep the mapped size information */ struct image_handle *ret; int binfd = -1, f_stat; struct stat statbuf; size_t ps = getpagesize (); ret = malloc(sizeof(struct image_handle)); if (!ret) return NULL; ret->speh.handle_size = sizeof(spe_program_handle_t); ret->speh.toe_shadow = NULL; binfd = open(filename, O_RDONLY); if (binfd < 0) goto ret_err; f_stat = fstat(binfd, &statbuf); if (f_stat < 0) goto ret_err; /* Sanity: is it executable ? */ if(!(statbuf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) { errno=EACCES; goto ret_err; } /* now store the size at the extra allocated space */ ret->map_size = (statbuf.st_size + ps - 1) & ~(ps - 1); ret->speh.elf_image = mmap(NULL, ret->map_size, PROT_WRITE | PROT_READ, MAP_PRIVATE, binfd, 0); if (ret->speh.elf_image == MAP_FAILED) goto ret_err; /*Verify that this is a valid SPE ELF object*/ if((verify_spe_elf_image((spe_program_handle_t *)ret))) goto ret_err; if (toe_ear(&ret->speh)) goto ret_err; /* ok */ close(binfd); return (spe_program_handle_t *)ret; /* err & cleanup */ ret_err: if (binfd >= 0) close(binfd); free(ret); return NULL; } int spe_close_image(spe_program_handle_t *handle) { int ret = 0; struct image_handle *ih; if (!handle) { errno = EINVAL; return -1; } ih = (struct image_handle *)handle; if (!ih->speh.elf_image || !ih->map_size) { errno = EINVAL; return -1; } if (ih->speh.toe_shadow) free(ih->speh.toe_shadow); ret = munmap(ih->speh.elf_image, ih->map_size ); free(handle); return ret; } void register_handler(void * handler, unsigned int callnum ) { handlers[callnum]=handler; } /** * Library API * */ void * spe_thread (void *ptr) { /* If the SPU_INFO (or SPU_DEBUG_START) environment variable is set, output a message to stderr telling the user how to attach a debugger to the new SPE thread. */ if (__env_spu_debug_start || __env_spu_info) { int tid = syscall (__NR_gettid); fprintf (stderr, "Starting SPE thread %p, to attach debugger use: spu-gdb -p %d\n", ptr, tid); /* In the case of SPU_DEBUG_START, actually wait until the user *has* attached a debugger to this thread. This is done here by doing an sigwait on the empty set, which will return with EINTR after the debugger has attached. */ if (__env_spu_debug_start) { sigset_t set; sigemptyset (&set); /* Use syscall to avoid glibc looping on EINTR. */ syscall (__NR_rt_sigtimedwait, &set, (void *) 0, (void *) 0, _NSIG / 8); } } return (void *) (unsigned long) do_spe_run (ptr); } void *spe_get_ls (speid_t speid) { struct thread_store *thread_store = speid; if (!srch_thread(speid)) return NULL; #ifdef SPE_NO_MMAP errno = EFAULT; return -1; #else return thread_store->mem_mmap_base; #endif } int spe_get_context(speid_t speid, struct spe_ucontext *uc) { printf("spe_get_context: not implemented in this release.\n"); errno=ENOSYS; return -1; } int spe_set_context(speid_t speid, struct spe_ucontext *uc) { printf("spe_set_context: not implemented in this release.\n"); errno=ENOSYS; return -1; } int __spe_get_context_fd(speid_t speid) { struct thread_store *thread_store = speid; if (!srch_thread(speid)) return -1; return thread_store->fd_run; } /* * mfc.h direct call-ins * * */ int spe_write_in_mbox (speid_t speid ,unsigned int data) { struct thread_store *thread_store = speid; int rc; if (!srch_thread(speid)) return -1; if (thread_store->thread_status == 99) return -1; rc = write(thread_store->fd_wbox, &data, 4); if (rc == 4) rc = 0; return rc; } int spe_stat_in_mbox (speid_t speid) { struct thread_store *thread_store = speid; int rc, ret; if (!srch_thread(speid)) return -1; rc = read(thread_store->fd_wbox_stat, &ret, 4); if (rc != 4) ret = -1; return ret; } unsigned int spe_read_out_mbox (speid_t speid) { struct thread_store *thread_store = speid; int rc; unsigned int ret; if (!srch_thread(speid)) return -1; rc = read(thread_store->fd_mbox, &ret, 4); if (rc != 4) ret = -1; return ret; } int spe_stat_out_mbox (speid_t speid) { struct thread_store *thread_store = speid; int rc, ret; if (!srch_thread(speid)) return -1; rc = read(thread_store->fd_mbox_stat, &ret, 4); if (rc != 4) ret = -1; return ret; } int spe_stat_out_intr_mbox (speid_t speid) { struct thread_store *thread_store = speid; int rc, ret; if (!srch_thread(speid)) return -1; rc = read(thread_store->fd_ibox_stat, &ret, 4); if (rc != 4) ret = -1; return ret; } unsigned int spe_read_out_intr_mbox(speid_t speid) { struct thread_store *thread_store = speid; int rc; unsigned int ret; if (!srch_thread(speid)) return -1; rc = read(thread_store->fd_ibox, &ret, 4); if (rc != 4) ret = -1; return ret; } int spe_write_signal (speid_t speid, unsigned int signal_reg, unsigned int data) { struct thread_store *thread_store = speid; int rc; if (!srch_thread(speid)) return -1; if (thread_store->thread_status == 99) return -1; if (signal_reg == SPE_SIG_NOTIFY_REG_1) rc = write(thread_store->fd_sig1, &data, 4); else if (signal_reg == SPE_SIG_NOTIFY_REG_2) rc = write(thread_store->fd_sig2, &data, 4); else return -1; if (rc == 4) rc = 0; return rc; } /** * do_spe_map_ps_area(spe, offset, fd, size) * * This is an internal function for mmapping part of the SPE problem state. * it will use either the 128k single problem state mapping on recent kernels * or the individual per-file mmap using the passed-in fd if the former is * not available. */ void *do_spe_map_ps_area(struct thread_store *spe, off_t offset, int fd, size_t size) { /* Check if 128k mapping is possible and not mapped yet */ if (spe->fd_psmap >= 0 && spe->ps_mmap_base == MAP_FAILED) { spe->ps_mmap_base = mmap(0, 0x20000, PROT_READ | PROT_WRITE, MAP_SHARED, spe->fd_psmap, 0); if (spe->ps_mmap_base == MAP_FAILED) return MAP_FAILED; } /* If we have 128k mapping, return an offset within */ if (spe->ps_mmap_base != MAP_FAILED) { if (offset > 0x20000 || (offset + size) > 0x20000) return MAP_FAILED; return spe->ps_mmap_base + offset; } /* Use the individual file mapping */ return mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); } /* * */ libspe-1.2.2/spe.h0000640000076400007640000000775510533602311013532 0ustar cellbldcellbld/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _spe_h_ #define _spe_h_ /* Definitions */ #define __PRINTF(fmt, args...) { fprintf(stderr,fmt , ## args); } #ifdef DEBUG #define DEBUG_PRINTF(fmt, args...) __PRINTF(fmt , ## args) #else #define DEBUG_PRINTF(fmt, args...) #endif struct thread_store { /* Note: The debugger accesses this data structure, and assumes it starts out with an spe_program_handle_t identifying the SPE executable running within this SPE thread. Everything below is private to libspe. */ spe_program_handle_t handle; pthread_t spe_thread; pthread_cond_t event_deliver; pthread_mutex_t event_lock; int fd_mem, fd_run, fd_mbox, fd_mbox_stat, fd_ibox, fd_ibox_stat, fd_wbox, fd_wbox_stat, fd_npc, fd_sig1, fd_sig2, fd_mfc, fd_cntl, fd_mss, fd_psmap, policy, priority, affinity_mask, spe_flags, npc, ret_status,event, ev_pipe[2]; spe_gid_t group_id; unsigned long mask; unsigned int flags; void *mem_mmap_base; void *ps_mmap_base; void *mss_mmap_base; void *mfc_mmap_base; void *cntl_mmap_base; void *signal1_mmap_base; void *signal2_mmap_base; unsigned long ev_data; int event_pending; int killed; int stop; int thread_status; void *app_data; }; /*Group members list */ struct grpListElem { struct grpListElem *next; struct thread_store *thread; }; struct group_store { int policy, priority, use_events; struct grpListElem *grp_members; int numListSize; int deleteMe; }; /*Groups List */ struct grpsElem { struct grpsElem *next; struct group_store *group; }; struct group_list { struct grpsElem *list_start; pthread_mutex_t mutex; int numListSize; }; struct spe_ctx { unsigned int npc; unsigned int status; unsigned long reg[128][4]; // size error for LP64 void *ls; }; struct poll_helper { int event; struct thread_store *thread; int type; int retfd; }; /* Low-level SPE execution API. */ extern struct thread_store *srch_thread(struct thread_store *thread); extern struct group_store *srch_group(struct group_store *group); extern int add_group_to_groups(struct group_store *gid); extern int add_thread_to_group(struct group_store *gid, struct thread_store *thread); extern int remove_thread_from_group(struct group_store *gid, struct thread_store *thread); extern void *spe_gid_setup(int policy, int priority, int use_events); extern void *spe_setup (spe_gid_t gid, spe_program_handle_t *handle, void *argp, void *envp, int flags); extern void spe_cleanup (void *spe); extern int do_spe_run (void *spe); extern unsigned int set_npc (void *spe, unsigned int npc); extern int validatefd(struct poll_helper *phelper, int pos, int fd); extern void *do_spe_map_ps_area(struct thread_store *spe, off_t offset, int fd, size_t size); extern void register_handler(void * handler, unsigned int callnum ); extern int check_priority(int policy, int priority); extern int remove_group_from_groups(struct group_store *gid); void env_check(void); void * spe_thread (void *ptr); /* * For testing purposes only */ #endif libspe-1.2.2/spe_exec.h0000640000076400007640000000253110533602311014521 0ustar cellbldcellbld/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _spe_exec_h_ #define _spe_exec_h_ #define SPE_LDR_START 0x0003fe00 #define SPE_PARAM_START 0x0003ff80 /* * struct spe_exec_params: * * Holds the (per thread) parameters for the spe program */ struct spe_exec_params { unsigned int gpr0[4]; /* entry point for application. */ unsigned int gpr3[4]; /* initial setting for $3 */ unsigned int gpr4[4]; /* initial setting for $4 */ unsigned int gpr5[4]; /* initial setting for $5 */ unsigned int gpr6[4]; /* initial setting for $6 */ }; #endif libspe-1.2.2/spethreads.c0000640000076400007640000005452310557663662015121 0ustar cellbldcellbld/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "libspe.h" #include "spe.h" #include "elf_loader.h" #include "spe_exec.h" #include "default_c99_handler.h" #include "default_posix1_handler.h" /* * Helpers * * */ static struct group_list grp_list = {NULL,PTHREAD_MUTEX_INITIALIZER,0}; extern int check_env; /** * Send data to a SPU in mbox when space is available. * * Helper function for internal libspe use. * * @param thread The SPE thread to send the mailbox message to * @param data Data to send to the mailbox * @return zero on success, non-zero on failure */ static int spe_send_in_mbox_synchronous(struct thread_store *thread, int data) { while (!spe_stat_in_mbox(thread)) ; return spe_write_in_mbox(thread, data); } /** * Initiate transfer of an isolated SPE app by the loader kernel. * * Helper function for internal libspe use. * * @param thread The SPE thread to load the app to * @param handle The handle to the spe program * @return zero on success, non-zero on failure; */ static int spe_start_isolated_app(struct thread_store *thread, spe_program_handle_t *handle) { uint64_t addr; uint32_t size, addr_h, addr_l; spe_spu_control_area_t *control_area; if (spe_parse_isolated_elf(handle, &addr, &size)) { DEBUG_PRINTF("%s: invalid isolated image\n", __FUNCTION__); errno = ENOEXEC; return -errno; } if (addr & 0xf) { DEBUG_PRINTF("%s: isolated image is incorrectly aligned\n", __FUNCTION__); errno = EINVAL; return -errno; } control_area = spe_get_ps_area(thread, SPE_CONTROL_AREA); if (!control_area) { DEBUG_PRINTF("%s: could not access SPE control area: %s\n", __FUNCTION__, strerror(errno)); return -errno; } DEBUG_PRINTF("%s: Waiting for spu loader to start\n", __FUNCTION__); while (control_area->SPU_Status & 0x200) sched_yield(); addr_l = (uint32_t)(addr & 0xffffffff); addr_h = (uint32_t)(addr >> 32); DEBUG_PRINTF("%s: Sending isolated app params: 0x%08x 0x%08x 0x%08x\n", __FUNCTION__, addr_h, addr_l, size); return spe_send_in_mbox_synchronous(thread, addr_h) || spe_send_in_mbox_synchronous(thread, addr_l) || spe_send_in_mbox_synchronous(thread, size); } /* Group defaults * */ int default_priority = 0; int default_policy = SCHED_OTHER; int default_eventmask = 0; //extern void * spe_thread (void *); int add_group_to_groups(struct group_store *gid) { struct grpsElem *listElem; listElem = malloc(sizeof *listElem); if (!listElem) { errno=ENOMEM; return -errno; } pthread_mutex_lock(&grp_list.mutex); listElem->group=gid; listElem->next=grp_list.list_start; grp_list.list_start=listElem; grp_list.numListSize++; pthread_mutex_unlock(&grp_list.mutex); return 0; } int add_thread_to_group(struct group_store *gid, struct thread_store *thread) { struct grpListElem *listElem; listElem = malloc(sizeof *listElem); if (!listElem) { errno=ENOMEM; return -errno; } pthread_mutex_lock(&grp_list.mutex); listElem->thread=thread; listElem->next=gid->grp_members; gid->grp_members=listElem; gid->numListSize++; pthread_mutex_unlock(&grp_list.mutex); return 0; } int remove_group_from_groups(struct group_store *gid) { pthread_mutex_lock(&grp_list.mutex); struct grpsElem *lgp = NULL; for (struct grpsElem *gp=grp_list.list_start ; gp !=NULL; gp=gp->next) { if (gp->group == gid) { if (gp->group->numListSize == 0) { // Delete the group if (lgp == NULL) { grp_list.list_start = gp->next; } else { lgp->next = gp->next; } free(gp); } pthread_mutex_unlock(&grp_list.mutex); return 0; } lgp = gp; } pthread_mutex_unlock(&grp_list.mutex); return 1; } int remove_thread_from_group(struct group_store *gid, struct thread_store *thread) { pthread_mutex_lock(&grp_list.mutex); if (gid->numListSize == 1) { struct grpListElem *p=gid->grp_members; gid->numListSize--; free(p); gid->grp_members = NULL; pthread_mutex_unlock(&grp_list.mutex); if (gid->deleteMe) { remove_group_from_groups(gid); } return 0; } for (struct grpListElem *p=gid->grp_members; p->next!=NULL; p=p->next) { struct grpListElem *np=p->next; if (np->thread==thread) { p->next=np->next; gid->numListSize--; free(np); pthread_mutex_unlock(&grp_list.mutex); return 0; } } pthread_mutex_unlock(&grp_list.mutex); errno = ESRCH; return -ESRCH; } struct thread_store * srch_thread(struct thread_store *thread) { pthread_mutex_lock(&grp_list.mutex); for (struct grpsElem *gp=grp_list.list_start ; gp !=NULL; gp=gp->next) { //printf("1\n"); struct group_store *gid = gp->group; for (struct grpListElem *p=gid->grp_members; p !=NULL; p=p->next) { //printf("2\n"); if (p->thread==thread) { pthread_mutex_unlock(&grp_list.mutex); return p->thread; } } } pthread_mutex_unlock(&grp_list.mutex); errno = ESRCH; return NULL; } struct group_store * srch_group(struct group_store *group) { pthread_mutex_lock(&grp_list.mutex); for (struct grpsElem *gp=grp_list.list_start ; gp !=NULL; gp=gp->next) { if (gp->group == group) { pthread_mutex_unlock(&grp_list.mutex); return gp->group; } } pthread_mutex_unlock(&grp_list.mutex); errno = ESRCH; return NULL; } void * spe_gid_setup(int policy, int priority, int use_events) { struct group_store *group_store; group_store = calloc (1, sizeof *group_store); if (!group_store) { DEBUG_PRINTF ("Could not allocate group store\n"); errno = ENOMEM; return NULL; } group_store->policy = policy; group_store->priority = priority; group_store->use_events = use_events; group_store->grp_members = NULL; group_store->numListSize = 0; group_store->deleteMe = 0; add_group_to_groups(group_store); return group_store; } spe_gid_t spe_create_group (int policy, int priority, int use_events) { struct group_store *group_store; /* Sanity: check for vaild policy/priority combination. */ if (!check_priority(policy, priority)) { errno=EINVAL; return NULL; } DEBUG_PRINTF ("spu_create_group(0x%x, 0x%x, 0x%x)\n", policy, priority, use_events); group_store=spe_gid_setup(policy, priority, use_events); DEBUG_PRINTF("gid is %p\n", group_store); return group_store; } int spe_destroy_group(spe_gid_t spe_gid) { struct group_store *gid = spe_gid; if ( gid != NULL && !srch_group(gid)) { errno = ESRCH; return -1; } gid->deleteMe=1; remove_group_from_groups(gid); return 0; } int spe_group_max (spe_gid_t spe_gid) { if ( spe_gid != NULL && !srch_group(spe_gid)) { errno = ESRCH; return -1; } DEBUG_PRINTF ("spu_group_max(0x%x)\n", spe_gid); return MAX_THREADS_PER_GROUP; } int spe_count_physical_spes(void) { char buff[256] = "/sys/devices/system/spu"; DIR *dirp; int ret = -2; struct dirent *dptr; DEBUG_PRINTF ("spe_count_physical_spes()\n"); // Count number of SPUs in /sys/devices/system/spu if((dirp=opendir(buff))==NULL) { fprintf(stderr,"Error opening %s ",buff); perror("dirlist"); return -1; } while(dptr=readdir(dirp)) { ret++; } closedir(dirp); return ret; } speid_t spe_create_thread (spe_gid_t gid, spe_program_handle_t *handle, void *argp, void *envp, unsigned long mask, int flags) { struct thread_store *thread_store; int rc; /* Sanity check */ if (!handle || (( flags & SPE_USER_REGS ) && !argp ) || ((flags & SPE_USER_REGS) && (flags & SPE_ISOLATE))) { errno=EINVAL; return NULL; } if ( gid != NULL && !srch_group(gid)) { errno = ESRCH; return NULL; } if ( mask == 0 || (mask & ((1<mask = mask; DEBUG_PRINTF ("pthread_create()\n"); rc = pthread_create (&thread_store->spe_thread, NULL, spe_thread, thread_store); if (rc) { perror ("pthread_create"); return NULL; } if (thread_store->flags & SPE_ISOLATE) { if (spe_start_isolated_app(thread_store, handle)) { DEBUG_PRINTF ("spe_start_isolated_app failed\n"); return NULL; } DEBUG_PRINTF ("isolated app info sent to spe\n"); } return thread_store; } int spe_recycle(speid_t spe, spe_program_handle_t *handle) { int ret; char buf = 0; struct thread_store *thread = (struct thread_store *)spe; if (!(thread->flags & SPE_ISOLATE)) { errno = EINVAL; return -errno; } thread->thread_status = 1; ret = pthread_create(&thread->spe_thread, NULL, spe_thread, thread); if (ret) return ret; return spe_start_isolated_app(spe, handle); } static inline int spe_wait_status(unsigned int spe_status_R) { unsigned int rc, term = 0; rc = (spe_status_R & 0xffff0000) >> 16; if (spe_status_R & 0x4) { /* SPE halted. */ term = SIGABRT; } else if (spe_status_R & 0x20) { /* SPE invalid instruction. */ term = SIGILL; } else if (spe_status_R & 0x40) { /* SPE invalid ch. */ term = SIGILL; } else if ((rc < 0x2000) || (rc > 0x20ff)) { /* Treat these as invalid stop codes. */ term = SIGILL; } else if (spe_status_R & 0x1) { /* Thread killed for undetermined reason. */ term = SIGKILL; } /* Return status that can be evaluated with WIFEXITED(), etc. */ return ((rc & 0xff) << 8) | (term & 0x7f); } int spe_wait(speid_t speid, int *status, int options) { struct thread_store *thread_store = speid; void *pthread_rc; int rc; if (!srch_thread(speid)) { return -1; } DEBUG_PRINTF("spu_wait(0x%x, %p, 0x%x)\n", speid, status, options); if (options & WNOHANG) { if (thread_store->thread_status != 99) { *status = 0; return 0; } } if (options & WUNTRACED) { if (thread_store->thread_status == 10 || thread_store->thread_status == 20 ) { *status = 0x4; } } rc = pthread_join(thread_store->spe_thread, &pthread_rc); if (rc) { DEBUG_PRINTF(" pthread_join failed, errno=%d\n", errno); return -1; } if (status) { *status = spe_wait_status(thread_store->ret_status); } if (!(options & WCONTINUED)) spe_cleanup(thread_store); DEBUG_PRINTF("Thread ended.\n"); return rc; } int spe_kill (speid_t speid, int sig) { struct thread_store *thread_store = speid; if (!srch_thread(speid)) { return -1; } if (sig == SIGCONT) { int stopped = 0; /* if (thread_store->thread_status == 2) { // Running on SPU pthread_kill (thread_store->spe_thread, SIGCONT); return 0; } */ pthread_mutex_lock(&thread_store->event_lock); stopped = thread_store->event_pending; if ( thread_store->stop || stopped ) { pthread_cond_signal(&thread_store->event_deliver); } pthread_mutex_unlock(&thread_store->event_lock); return 0; } if (sig == SIGKILL) { int stopped; int ret = 0; pthread_mutex_lock(&thread_store->event_lock); /* Tell the thread that it is to be killed.*/ thread_store->killed = 1; /* See if it is halted and waiting */ stopped = thread_store->event_pending; if (stopped) { pthread_cond_signal(&thread_store->event_deliver); } else { ret = pthread_cancel (thread_store->spe_thread); } pthread_mutex_unlock(&thread_store->event_lock); return ret; } if (sig == SIGSTOP) { /* if (thread_store->thread_status == 2) // Running on SPU pthread_kill (thread_store->spe_thread, SIGSTOP); else */ /* Tell the thread that it is to stop.*/ thread_store->stop = 1; return 0; } errno = EINVAL; return -1; } int validatefd(struct poll_helper *phelper, int pos, int fd) { int i; for(i=0;igrp_members; DEBUG_PRINTF("spe_get_event():\n"); DEBUG_PRINTF(" using group : %p\n", group); DEBUG_PRINTF(" with members : %i\n", group->numListSize); for ( j=0 ; j < group->numListSize; j++) { struct thread_store *thread = elem->thread; DEBUG_PRINTF(" scan member : %p\n", thread); // Scan for present events in the thread structures of SPEs if (thread->event != 0 && thread->event & pevents[i].events) { int pipeval,ret; DEBUG_PRINTF(" has event ! : 0x%04x\n", thread->event); //Found an event we're looking for. ret_events++; //Fill out return struct. pevents[i].revents = thread->event; pevents[i].speid = thread; pevents[i].data = thread->ev_data; //Empty the pipe ret=read(thread->ev_pipe[0], &pipeval, 4); thread->ev_data = 0; thread->event = 0; pthread_mutex_unlock(&grp_list.mutex); return ret_events; } //Decide on what fd's to poll on if (pevents[i].events & (SPE_EVENT_MAILBOX)) { numSPEsToPoll++; } if (pevents[i].events & (SPE_EVENT_TAG_GROUP)) { numSPEsToPoll++; } if (pevents[i].events & (SPE_EVENT_STOP | SPE_EVENT_DMA_ALIGNMENT | SPE_EVENT_SPE_ERROR | SPE_EVENT_SPE_DATA_SEGMENT | SPE_EVENT_SPE_DATA_STORAGE | SPE_EVENT_SPE_TRAPPED | SPE_EVENT_THREAD_EXIT )) { numSPEsToPoll++; } elem=elem->next; } } if(numSPEsToPoll == 0) { pthread_mutex_unlock(&grp_list.mutex); errno=EINVAL; return -1; } if (ret_events > 0) { //printf("P1\n"); //DEBUG_PRINTF(" returning ! : 0xi\n", ret_events); pthread_mutex_unlock(&grp_list.mutex); return ret_events; } DEBUG_PRINTF(" number of fd : %i\n", numSPEsToPoll); SPEfds=malloc (numSPEsToPoll * sizeof(struct pollfd)); phelper=malloc (numSPEsToPoll * sizeof(struct poll_helper)); // Set up all necessary fds to poll on and remeber what they are for. for (i=0 ; i < nevents ; i++) { int j; struct group_store *group = pevents[i].gid; struct grpListElem *elem = group->grp_members; for ( j=0 ; j < group->numListSize; j++) { struct thread_store *thread = elem->thread; if (pevents[i].events & (SPE_EVENT_MAILBOX)) { SPEfds[setupSPEs].fd=thread->fd_ibox; SPEfds[setupSPEs].events=POLLIN; phelper[setupSPEs].event=i; phelper[setupSPEs].thread=thread; phelper[setupSPEs].retfd=-1; phelper[setupSPEs].type=1; //printf("1\n"); setupSPEs++; } if (pevents[i].events & (SPE_EVENT_STOP | SPE_EVENT_DMA_ALIGNMENT | SPE_EVENT_SPE_ERROR | SPE_EVENT_SPE_DATA_SEGMENT | SPE_EVENT_INVALID_DMA_CMD | SPE_EVENT_SPE_DATA_STORAGE | SPE_EVENT_SPE_TRAPPED | SPE_EVENT_THREAD_EXIT )) { SPEfds[setupSPEs].fd=thread->ev_pipe[0]; SPEfds[setupSPEs].events=POLLIN; phelper[setupSPEs].event=i; phelper[setupSPEs].thread=thread; phelper[setupSPEs].retfd=-1; phelper[setupSPEs].type=2; //printf("2\n"); setupSPEs++; } if (pevents[i].events & (SPE_EVENT_TAG_GROUP)) { SPEfds[setupSPEs].fd=thread->fd_mfc; SPEfds[setupSPEs].events=POLLIN; phelper[setupSPEs].event=i; phelper[setupSPEs].thread=thread; phelper[setupSPEs].retfd=-1; phelper[setupSPEs].type=3; if (SPEfds[setupSPEs].fd == -1) fprintf(stderr, "Warning: spe_get_events: attempting " "to wait for tag group without DMA support\n"); //printf("3\n"); setupSPEs++; } elem=elem->next; } } if (setupSPEs != numSPEsToPoll) { DEBUG_PRINTF("ERROR:Thread number mismatch."); free(SPEfds); free(phelper); pthread_mutex_unlock(&grp_list.mutex); errno = EFAULT; return -1; } pthread_mutex_unlock(&grp_list.mutex); DEBUG_PRINTF("Polling for %i fd events.\n",setupSPEs); pollRet = poll(SPEfds, setupSPEs, timeout); DEBUG_PRINTF("Poll returned %i events.\n",pollRet); ret_events = 0; // Timeout. if (pollRet == 0) { free(SPEfds); free(phelper); return 0; } for (i=0 ; i < setupSPEs ; i++ ) { if (SPEfds[i].revents != 0 && pevents[phelper[i].event].speid == NULL ) { int rc,data; if (validatefd(phelper,i,SPEfds[i].fd)) { switch (phelper[i].type) { case 1: // Read ibox data if present rc = read(SPEfds[i].fd, &data, 4); if (rc == 4) { phelper[i].retfd=SPEfds[i].fd; pevents[phelper[i].event].data = data; pevents[phelper[i].event].speid = phelper[i].thread; pevents[phelper[i].event].revents = SPE_EVENT_MAILBOX; ret_events++; } else { phelper[i].retfd=SPEfds[i].fd; pevents[phelper[i].event].data = errno; pevents[phelper[i].event].speid = phelper[i].thread; pevents[phelper[i].event].revents = SPE_EVENT_ERR; ret_events++; } break; case 2: // Read pipe data if present rc = read(SPEfds[i].fd, &data, 4); //pevents[phelper[i].event].revents = pevents[phelper[i].event].revents | data; phelper[i].retfd=SPEfds[i].fd; pevents[phelper[i].event].revents = data; pevents[phelper[i].event].speid = phelper[i].thread; pevents[phelper[i].event].data = phelper[i].thread->ev_data; phelper[i].thread->ev_data = 0; phelper[i].thread->event = 0; ret_events++; break; case 3: // Read tag group data if present rc = read(SPEfds[i].fd, &data, 4); if (rc == 4) { phelper[i].retfd=SPEfds[i].fd; pevents[phelper[i].event].data = data; pevents[phelper[i].event].speid = phelper[i].thread; pevents[phelper[i].event].revents = SPE_EVENT_TAG_GROUP; ret_events++; } else { phelper[i].retfd=SPEfds[i].fd; pevents[phelper[i].event].data = errno; pevents[phelper[i].event].speid = phelper[i].thread; pevents[phelper[i].event].revents = SPE_EVENT_ERR; ret_events++; } break; } } } } free(SPEfds); free(phelper); //printf("P2\n"); return ret_events; } int spe_get_threads(spe_gid_t gid, speid_t *spe_ids) { struct group_store *group = gid; int i; if ( gid != NULL && !srch_group(gid)) { errno = ESRCH; return -1; } if (!spe_ids) { return group->numListSize; } else { struct grpListElem *elem = group->grp_members; for(i=0; i < group->numListSize ; i++) { spe_ids[i] = elem->thread; elem=elem->next; } } return i; } int spe_get_priority(spe_gid_t gid) { struct group_store *group_store = gid; if ( gid != NULL && !srch_group(gid)) { errno = ESRCH; return -1; } return group_store->priority; } int spe_set_priority(spe_gid_t gid, int priority) { struct group_store *group_store = gid; if ( gid != NULL && !srch_group(gid)) { errno = ESRCH; return -1; } /* Sanity: check for vaild policy/priority combination. */ if (!check_priority(group_store->policy, priority)) { errno=EINVAL; return -1; } group_store->priority=priority; /*int pthread_setschedparam(pthread_t target_thread, int policy, const struct sched_param *param);*/ return 0; } int check_priority(int policy, int priority) { switch (policy) { case SCHED_RR: if (1 > priority || priority > 99) { return 0; } break; case SCHED_FIFO: if (1 > priority || priority > 99) { return 0; } break; case SCHED_OTHER: if (0 > priority || priority > 39) { return 0; } break; } return 1; } int spe_get_policy(spe_gid_t gid) { struct group_store *group_store = gid; if ( gid != NULL && !srch_group(gid)) { errno = ESRCH; return -1; } return group_store->policy; } spe_gid_t spe_get_group (speid_t speid) { struct thread_store *thread_store = speid; if (!srch_thread(speid)) { return NULL; } return thread_store->group_id; } int spe_get_affinity( speid_t speid, unsigned long *mask) { int result = 0; if (!srch_thread(speid)) { return -1; } printf("spe_get_affinity() not implemented in this release.\n"); return result; } int spe_set_affinity(speid_t speid, unsigned long mask) { int result = 0; if (!srch_thread(speid)) { return -1; } printf("spe_set_affinity() not implemented in this release.\n"); return result; } int spe_group_defaults(int policy, int priority, int spe_events) { /* Sanity: check for vaild policy/priority combination. */ if (!check_priority(policy, priority)) { errno=EINVAL; return -1; } default_policy = policy; default_priority = priority; default_eventmask= spe_events; return 0; } int spe_set_app_data( speid_t speid, void* data) { struct thread_store *thread_store = speid; if (!srch_thread(speid)) return -1; thread_store->app_data = data; return 0; } int spe_get_app_data( speid_t speid, void** p_data) { struct thread_store *thread_store = speid; if (!srch_thread(speid)) return -1; *p_data = thread_store->app_data; return 0; } libspe-1.2.2/tests/0000755000076400007640000000000010575455116013741 5ustar cellbldcellbldlibspe-1.2.2/tests/elfspe/0000755000076400007640000000000010575455116015217 5ustar cellbldcellbldlibspe-1.2.2/tests/elfspe/spe-helloworld.c0000640000076400007640000000011110533602312020272 0ustar cellbldcellbld#include int main() { printf("Hello World.\n"); return 0; } libspe-1.2.2/tests/elfspe/Makefile0000640000076400007640000000241310533602312016635 0ustar cellbldcellbld#* #* libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS #* Copyright (C) 2005 IBM Corp. #* #* This library is free software; you can redistribute it and/or modify it #* under the terms of the GNU Lesser General Public License as published by #* the Free Software Foundation; either version 2.1 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 Lesser General Public #* License for more details. #* #* You should have received a copy of the GNU Lesser General Public License #* along with this library; if not, write to the Free Software Foundation, #* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #* CC := gcc SPECC := spu-gcc CFLAGS := -O2 -Wall -I../.. -I../../include -g SPECFLAGS := -O2 -Wall -I../../include SPELDFLAGS := -L/usr/spu/lib LIBS := -L../.. -lspe -lpthread SPELIBS := -lc -lgloss SPE_OBJS := spe-helloworld OBJS := runspe all: $(SPE_OBJS) $(OBJS) clean: rm -f $(SPE_OBJS) $(OBJS) $(SPE_OBJS): %: %.c $(SPECC) $(SPECFLAGS) $(SPELDFLAGS) -o $@ $< $(SPELIBS) $(OBJS): %: %.c $(CC) $(CFLAGS) -o $@ $< $(LIBS) libspe-1.2.2/tests/elfspe/runspe.c0000640000076400007640000000321410533602312016655 0ustar cellbldcellbld/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include int main(int argc, char* argv[]) { spe_program_handle_t *binary; speid_t spe_thread; spe_gid_t spe_group; int max_spe, status; if (argc != 2) { printf("usage: pu spu-executable\n"); exit(1); } binary = spe_open_image(argv[1]); if (!binary) exit(2); spe_group = spe_create_group(SCHED_OTHER, 0, 0); if (!spe_group) { printf("error: create_group.\n"); } max_spe = spe_group_max(spe_group); printf("info: group_max=%i\n", max_spe); spe_thread = spe_create_thread(spe_group, binary, NULL, NULL, 0xffff, 0); if (spe_thread) { spe_wait(spe_thread, &status,0); printf("Thread returned status: %04x\n",status); } else perror("Could not create thread"); spe_close_image(binary); return 0; } libspe-1.2.2/tests/elfspe/runtest.sh0000750000076400007640000000015210533602312017235 0ustar cellbldcellbld#!/bin/bash echo Registering elfspe. ../../elfspe-register echo Running spe-helloworld. ./spe-helloworld libspe-1.2.2/tests/dma/0000755000076400007640000000000010575455116014502 5ustar cellbldcellbldlibspe-1.2.2/tests/dma/Makefile0000640000076400007640000000253710533602311016126 0ustar cellbldcellbld#* #* libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS #* Copyright (C) 2005 IBM Corp. #* #* This library is free software; you can redistribute it and/or modify it #* under the terms of the GNU Lesser General Public License as published by #* the Free Software Foundation; either version 2.1 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 Lesser General Public #* License for more details. #* #* You should have received a copy of the GNU Lesser General Public License #* along with this library; if not, write to the Free Software Foundation, #* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #* CC := gcc SPECC := spu-gcc CTAGS = ctags CFLAGS := -O2 -m32 -Wall -I../.. -I../../include -g SPECFLAGS := -O2 -Wall -I../../include -Wno-main LDFLAGS := -m32 LIBS := -L../.. -lspe -lpthread SPE_OBJS := spe-dma-read spe-dma-write OBJS := ppe-dma-test all: $(OBJS) $(SPE_OBJS) clean: rm -f $(OBJS) $(SPE_OBJS) ppe-dma-test: ppe-dma-test.c $(CC) -o $@ $< $(CFLAGS) $(LDFLAGS) $(LIBS) spe-dma-read: spe-dma-read.c $(SPECC) $(SPECFLAGS) -o $@ $< spe-dma-write: spe-dma-write.c $(SPECC) $(SPECFLAGS) -o $@ $< libspe-1.2.2/tests/dma/spe-dma-read.c0000640000076400007640000000112610533602311017062 0ustar cellbldcellbld#include typedef union { unsigned long long ull; unsigned int vp[2]; } addr64; volatile int result __attribute__ ((aligned (128))); int main (int spuid, addr64 argp, addr64 envp) { unsigned long long argAddress = argp.ull; /* Write to specified address */ result = 23; __builtin_si_wrch((22), __builtin_si_from_uint(1)); spu_mfcdma32((void *) &result, argAddress, 4, 0, (((0) << 24) | ((0) << 16) | (0x40))); spu_mfcstat(0x2); /* Done */ return result; } libspe-1.2.2/tests/dma/spe-dma-write.c0000640000076400007640000000107710533602311017306 0ustar cellbldcellbld#include "spu_intrinsics.h" typedef union { unsigned long long ull; unsigned int vp[2]; } addr64; int result __attribute__ ((aligned (128))); int main ( int spuid, addr64 argp, addr64 envp) { unsigned long long argAddress = argp.ull; /* Write to specified address */ result = 42; spu_mfcdma32 (&result, argAddress, 4, 0, (((0) << 24) | ((0) << 16) | (0x20))); __builtin_si_wrch((22),__builtin_si_from_uint(1)); spu_mfcstat(0x2); /* Done */ return 0; } libspe-1.2.2/tests/dma/ppe-dma-test.c0000640000076400007640000000171510533602311017127 0ustar cellbldcellbld#include #include #include int main(int argc, char* argv[]) { spe_program_handle_t *binary; speid_t threadnum; int status; static int test_result __attribute__ ((aligned (128))); /* DMA - Write test. */ binary = spe_open_image("spe-dma-write"); if (!binary) exit(2); printf("Test result Addr: %p\n",&test_result); threadnum = spe_create_thread(0, binary, &test_result, NULL, 0xffff, 0); spe_wait(threadnum,&status,0); printf("Thread returned status: %04x\n",status); printf("Test result: %04x\n",test_result); spe_close_image(binary); /* DMA - Read test. */ binary = spe_open_image("spe-dma-read"); if (!binary) exit(2); threadnum = spe_create_thread(0, binary, &test_result, NULL, 0xffff, 0); spe_wait(threadnum,&status,0); printf("Thread returned status: %04x\n",status); printf("Test result: %04x\n",test_result); spe_close_image(binary); return 0; } libspe-1.2.2/tests/start-stop/0000755000076400007640000000000010575455116016061 5ustar cellbldcellbldlibspe-1.2.2/tests/start-stop/ppe-start-stop.c0000640000076400007640000000321410533602313021106 0ustar cellbldcellbld/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include int main(int argc, char* argv[]) { spe_program_handle_t *binary; speid_t spe_thread; spe_gid_t spe_group; int max_spe, status; if (argc != 2) { printf("usage: pu spu-executable\n"); exit(1); } binary = spe_open_image(argv[1]); if (!binary) exit(2); spe_group = spe_create_group(SCHED_OTHER, 0, 0); if (!spe_group) { printf("error: create_group.\n"); } max_spe = spe_group_max(spe_group); printf("info: group_max=%i\n", max_spe); spe_thread = spe_create_thread(spe_group, binary, NULL, NULL, 0xffff, 0); if (spe_thread) { spe_wait(spe_thread, &status,0); printf("Thread returned status: %04x\n",status); } else perror("Could not create thread"); spe_close_image(binary); return 0; } libspe-1.2.2/tests/start-stop/Makefile0000640000076400007640000000240310533602313017477 0ustar cellbldcellbld#* #* libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS #* Copyright (C) 2005 IBM Corp. #* #* This library is free software; you can redistribute it and/or modify it #* under the terms of the GNU Lesser General Public License as published by #* the Free Software Foundation; either version 2.1 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 Lesser General Public #* License for more details. #* #* You should have received a copy of the GNU Lesser General Public License #* along with this library; if not, write to the Free Software Foundation, #* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #* CC := gcc SPECC := spu-gcc CTAGS = ctags CFLAGS := -O2 -m32 -Wall -g -I../.. SPECFLAGS := -O2 -Wall LDFLAGS := -m32 LIBS := -L../.. -lspe -lpthread SPE_OBJS := spe-start-stop OBJS := ppe-start-stop all: $(OBJS) $(SPE_OBJS) clean: rm -f $(OBJS) $(SPE_OBJS) ppe-start-stop: ppe-start-stop.c ../../libspe.a $(CC) -o $@ $< $(CFLAGS) $(LDFLAGS) $(LIBS) spe-start-stop: spe-start-stop.c $(SPECC) $(SPECFLAGS) -o $@ $< libspe-1.2.2/tests/start-stop/spe-start-stop.c0000640000076400007640000000157110533602313021115 0ustar cellbldcellbld/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ int main(void) { return 0; } libspe-1.2.2/tests/Makefile0000640000076400007640000000205210533602313015357 0ustar cellbldcellbld#* #* libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS #* Copyright (C) 2005 IBM Corp. #* #* This library is free software; you can redistribute it and/or modify it #* under the terms of the GNU Lesser General Public License as published by #* the Free Software Foundation; either version 2.1 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 Lesser General Public #* License for more details. #* #* You should have received a copy of the GNU Lesser General Public License #* along with this library; if not, write to the Free Software Foundation, #* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #* tests: make -C start-stop make -C dma make -C event make -C ft make -C elfspe clean: make -C start-stop clean make -C dma clean make -C event clean make -C ft clean make -C elfspe clean libspe-1.2.2/tests/app_data/0000755000076400007640000000000010575455116015512 5ustar cellbldcellbldlibspe-1.2.2/tests/app_data/Makefile0000640000076400007640000000233710533602312017135 0ustar cellbldcellbld#* #* libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS #* Copyright (C) 2005 IBM Corp. #* #* This library is free software; you can redistribute it and/or modify it #* under the terms of the GNU Lesser General Public License as published by #* the Free Software Foundation; either version 2.1 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 Lesser General Public #* License for more details. #* #* You should have received a copy of the GNU Lesser General Public License #* along with this library; if not, write to the Free Software Foundation, #* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #* CC := gcc SPECC := spu-gcc CTAGS = ctags CFLAGS += -O2 -Wall -g -I../.. SPECFLAGS := -O2 -Wall LDFLAGS := $(CFLAGS) LIBS := -L../.. -lspe -lpthread SPE_OBJS := spe_prog OBJS := app_data all:$(SPE_OBJS) $(OBJS) clean: rm -f $(OBJS) $(SPE_OBJS) app_data: app_data.c ../../libspe.a $(CC) -o $@ $< $(CFLAGS) $(LDFLAGS) $(LIBS) spe_prog: spe_prog.c $(SPECC) $(SPECFLAGS) -o $@ $< libspe-1.2.2/tests/app_data/app_data.c0000640000076400007640000000244510533602312017412 0ustar cellbldcellbld #include #include #include #define NUM_SPE 4 spe_program_handle_t *spe_prog; struct spe_data { long last_data; }; void handle_event(struct spe_data *spe, struct spe_event *event) { printf(">> %ld\n", spe->last_data); //spe->last_data = event->data; } int main(int argc, char **argv) { speid_t speid[NUM_SPE]; spe_gid_t spe_gid; struct spe_data spe_data[NUM_SPE]; int done; int i; spe_prog = spe_open_image("spe_prog"); spe_gid = spe_create_group(0, 0, 1); for (i = 0; i < NUM_SPE; i++) { speid[i] = spe_create_thread(spe_gid, spe_prog, NULL, NULL, 0xffff, 0); /* set application data. */ spe_data[i].last_data = i; spe_set_app_data(speid[i], &spe_data[i]); } done = 0; while (done < NUM_SPE) { struct spe_event event; struct spe_data *cur_spe; event.gid = spe_gid; event.events = SPE_EVENT_MAILBOX | SPE_EVENT_THREAD_EXIT; spe_get_event(&event, 1, -1); switch (event.revents) { case SPE_EVENT_MAILBOX: /* get application data and handle the event. */ spe_get_app_data(event.speid, (void **)&cur_spe); handle_event(cur_spe, &event); break; case SPE_EVENT_THREAD_EXIT: spe_get_app_data(event.speid, (void **)&cur_spe); handle_event(cur_spe, &event); done++; break; } } } libspe-1.2.2/tests/app_data/spe_prog.c0000640000076400007640000000011510533602312017447 0ustar cellbldcellbld #include int main(void) { printf("Hello World\n"); return 0; } libspe-1.2.2/tests/event/0000755000076400007640000000000010575455116015062 5ustar cellbldcellbldlibspe-1.2.2/tests/event/ppe-start-stop.c0000640000076400007640000000653410533602313020117 0ustar cellbldcellbld/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include int main(int argc, char* argv[]) { spe_program_handle_t *binary,*binary1; speid_t spe_thread,spe_thread1; spe_gid_t spe_group; int max_spe, status; int numthread = 2; if (argc != 2) { printf("usage: pu spu-executable\n"); exit(1); } binary = spe_open_image(argv[1]); if (!binary) exit(2); binary1 = spe_open_image(argv[1]); if (!binary1) exit(2); spe_group = spe_create_group(SCHED_OTHER, 0, 1); if (!spe_group) { printf("error: create_group.\n"); } max_spe = spe_group_max(spe_group); printf("info: group_max=%i\n", max_spe); spe_thread = spe_create_thread(spe_group, binary, NULL, NULL, 0xffff, 0); usleep(500000); spe_thread1 = spe_create_thread(spe_group, binary, NULL, NULL, 0xffff, 0); if (!spe_thread) { perror("Could not create thread"); return -1; } while (1==1) { struct spe_event myevent; int ret; myevent.gid = spe_group; myevent.events = SPE_EVENT_STOP | SPE_EVENT_THREAD_EXIT ; ret = spe_get_event( &myevent,1, 100); if (!ret) { printf("get_event: timeout\n"); } else { printf("get_event: revents=0x%04x\n",myevent.revents); printf("get_event: data=0x%04lx\n",myevent.data); printf("get_event: speid=%p\n",myevent.speid); spe_kill(myevent.speid,SIGCONT); if (myevent.data == 0x1199) { break; } } } usleep(200000); while (1==1) { struct spe_event myevent[2]; int ret; myevent[0].gid = spe_group; myevent[0].events = SPE_EVENT_STOP | SPE_EVENT_THREAD_EXIT; myevent[1].gid = spe_group; myevent[1].events = SPE_EVENT_MAILBOX; ret = spe_get_event(&myevent[0], 2, 100); if (!ret) { printf("get_event: timeout\n"); } else { printf("get_event: Got %i events.\n",ret); printf("get_event[0]: revents=0x%04x\n",myevent[0].revents); printf("get_event[0]: data=0x%04lx\n",myevent[0].data); printf("get_event[0]: speid=%p\n",myevent[0].speid); printf("get_event[1]: revents=0x%04x\n",myevent[1].revents); printf("get_event[1]: data=0x%04lx\n",myevent[1].data); printf("get_event[1]: speid=%p\n",myevent[1].speid); if (myevent[0].revents == SPE_EVENT_STOP) spe_kill(myevent[0].speid,SIGCONT); if (myevent[0].revents == SPE_EVENT_THREAD_EXIT) { spe_wait(myevent[0].speid, &status,0); numthread--; if (!numthread) break; } } } spe_close_image(binary); spe_close_image(binary1); return 0; } libspe-1.2.2/tests/event/Makefile0000640000076400007640000000240310533602313016500 0ustar cellbldcellbld#* #* libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS #* Copyright (C) 2005 IBM Corp. #* #* This library is free software; you can redistribute it and/or modify it #* under the terms of the GNU Lesser General Public License as published by #* the Free Software Foundation; either version 2.1 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 Lesser General Public #* License for more details. #* #* You should have received a copy of the GNU Lesser General Public License #* along with this library; if not, write to the Free Software Foundation, #* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #* CC := gcc SPECC := spu-gcc CTAGS = ctags CFLAGS := -O2 -m32 -Wall -g -I../.. SPECFLAGS := -O2 -Wall LDFLAGS := -m32 LIBS := -L ../.. -lspe -lpthread SPE_OBJS := spe-start-stop OBJS := ppe-start-stop all: $(OBJS) $(SPE_OBJS) clean: rm -f $(OBJS) $(SPE_OBJS) ppe-start-stop: ppe-start-stop.c ../../libspe.a $(CC) -o $@ $< $(CFLAGS) $(LDFLAGS) $(LIBS) spe-start-stop: spe-start-stop.c $(SPECC) $(SPECFLAGS) -o $@ $< libspe-1.2.2/tests/event/spe-start-stop.c0000640000076400007640000000244510533602313020117 0ustar cellbldcellbld/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include int main(void) { int i,j,a[128]; for(i=0; i< 1500000 ; i++) { for(j=0; j< 128; j++) { a[j] += i; } } si_stop(0x1199); for(i=0; i< 1500000 ; i++) { for(j=0; j< 128; j++) { a[j] += i; } } // spu_writech(mfc_wr_intr_mailbox, 0xaabd); spu_writech(SPU_WrOutIntrMbox, 0xaabd); for(i=0; i< 1500000 ; i++) { for(j=0; j< 128; j++) { a[j] += i; } } si_stop(0x119A); return 0; } libspe-1.2.2/tests/ft/0000755000076400007640000000000010575455116014352 5ustar cellbldcellbldlibspe-1.2.2/tests/ft/spe-test-ibox2.c0000640000076400007640000000256610533602311017271 0ustar cellbldcellbld/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include void delay(void) { int i,j,a[128]; for(i=0; i< 200000 ; i++) { for(j=0; j< 128; j++) { a[j] += i; } } } int main(void) { unsigned int data; delay(); /* send a first event */ spu_writech(SPU_WrOutIntrMbox, 0xf00); /* wait for app to get it */ data = spu_readch(SPU_RdInMbox); delay(); /* send the second event that used to be broken */ spu_writech(SPU_WrOutIntrMbox, 0xbaa); /* wait for signal to finish */ data = spu_readch(SPU_RdInMbox); return 0; } libspe-1.2.2/tests/ft/Makefile0000640000076400007640000000251310533602311015770 0ustar cellbldcellbld#* #* libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS #* Copyright (C) 2005 IBM Corp. #* #* This library is free software; you can redistribute it and/or modify it #* under the terms of the GNU Lesser General Public License as published by #* the Free Software Foundation; either version 2.1 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 Lesser General Public #* License for more details. #* #* You should have received a copy of the GNU Lesser General Public License #* along with this library; if not, write to the Free Software Foundation, #* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #* CC := gcc SPECC := spu-gcc CTAGS = ctags CFLAGS := -O2 -Wall -I../.. -I../../include -g SPECFLAGS := -O2 -Wall -I../../include LDFLAGS := LIBS := -L../.. -lspe -lpthread SPE_OBJS := spe-test-block spe-test-pause spe-test-start-stop spe-test-mboxwait SPE_OBJS += spe-test-ppedma spe-test-ibox2 spe-test-mbox-block OBJS := ft all: $(OBJS) $(SPE_OBJS) clean: rm -f $(OBJS) $(SPE_OBJS) ft: ft.c $(CC) -o $@ $< $(CFLAGS) $(LDFLAGS) $(LIBS) $(SPE_OBJS): %: %.c $(SPECC) $(SPECFLAGS) -o $@ $< libspe-1.2.2/tests/ft/ft.c0000640000076400007640000006116110533602311015111 0ustar cellbldcellbld/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include static int basic_test(void) { spe_program_handle_t *binary[16]; speid_t spe_thread[256]; spe_gid_t spe_group; spe_gid_t spe_groups[16]; int result = 0; int i, j, a, max_spe, threads, status, ret; static int test_result __attribute__ ((aligned(128))); /* Basic Test */ printf("\nStep 1: spe_create_group() "); spe_group = spe_create_group(SCHED_OTHER, 0, 0); if (!spe_group) { printf("error: create_group.\n"); result++; } printf("\nStep 1a: spe_destroy_group() "); if (spe_destroy_group(spe_group)) { printf("error: destroy_group.\n"); } if (spe_destroy_group(spe_group)) { printf("Group gone."); } spe_group = spe_create_group(SCHED_OTHER, 0, 0); if (!spe_group) { printf("error: create_group.\n"); result++; } printf(" OK.\n"); printf(" spe_group=%p.\n",spe_group); printf("\nStep 2a: spe_group_max() returns:"); max_spe = spe_group_max(spe_group); printf("%i\n", max_spe); printf("\nStep 2b: spe_count_physical_spes() returns:"); max_spe = spe_count_physical_spes(); printf("%i\n", max_spe); printf("\nStep 3: spe_get_threads(spe_gid_t,NULL) returns:"); threads = spe_get_threads(spe_group,NULL); printf("%i ", threads); if(threads) { printf(" ERROR.\n"); result++; } else printf(" OK.\n"); printf("\nStep 4a: spe_open_image(\"spe-test-pause\") "); binary[0] = spe_open_image("spe-test-pause"); if (!binary[0]) { printf(" ERROR.\n"); exit(2); } printf(" OK.\n"); printf("\nStep 4b: spe_open_image(\"spe-test-pause\") (again) "); binary[1] = spe_open_image("spe-test-pause"); if (!binary[1]) { printf(" ERROR.\n"); exit(2); } printf(" OK.\n"); printf("\nStep 5a: spe_create_thread() "); spe_thread[0] = spe_create_thread(spe_group, binary[0], &test_result, NULL, 0xffff, 0); if (!spe_thread[0]) { printf(" ERROR.\n"); exit(2); } else { printf("OK.\n"); printf(" Returned speid=%p\n",spe_thread[0]); } usleep(500000); printf("\nStep 5b: spe_create_thread() (again) "); spe_thread[1] = spe_create_thread(spe_group, binary[1], &test_result, NULL, 0xffff, 0); if (!spe_thread[1]) { printf(" ERROR.\n"); exit(2); } else { printf("OK.\n"); printf(" Returned speid=%p\n",spe_thread[1]); } printf("\nStep 5c: spe_destroy_group() (delayed)"); if (spe_destroy_group(spe_group)) { printf("error: destroy_group.\n"); } printf("\nStep 6: spe_get_threads(spe_gid_t,NULL) returns:"); threads = spe_get_threads(spe_group,NULL); printf("%i ", threads); if (threads != 2) { printf(" ERROR.\n"); result++; } else { speid_t speids[16]; int i; printf(" OK.\n"); threads=spe_get_threads(spe_group,speids); for (i=0 ; i= timeout) { fprintf(stderr, "spe_get_event: probably timed out\n"); return 4; } *data = e.data; if (e.revents != SPE_EVENT_MAILBOX) { fprintf(stderr, "spe_get_event: unexpected event %d\n", e.revents); return 5; } if (e.speid != s) { fprintf(stderr, "spe_get_event: unexpected speid %p\n", e.speid); return 6; } return 0; } static int ppe_ibox_test(void) { spe_program_handle_t *binary; speid_t spe_thread; spe_gid_t spe_group; const uint32_t mbox_magic = 0xDEAD4EAD; uint32_t mbox_data; int status; int ret; static int test_result __attribute__ ((aligned(128))); binary = spe_open_image("spe-test-ppedma"); if (!binary) { perror("spe_open_image"); return 1; } spe_group = spe_create_group(SCHED_OTHER, 0, 0); if (!spe_group) { perror("spe_create_group"); return 2; } spe_thread = spe_create_thread(spe_group, binary, &test_result, NULL, 0xffff, 0); if (!spe_thread) { perror("spe_create_thread"); return 3; } ret = ppe_test_read_ibox(spe_group, spe_thread, &mbox_data); if (ret) return 5; ret = spe_write_in_mbox (spe_thread, mbox_magic); if (ret) { perror("spe_write_in_mbox"); return 6; } ret = spe_wait(spe_thread, &status, 0); if (ret) { perror("spe_wait"); return 7; } return 0; } #if 0 static int ppe_ibox2_test(void) { /* one bug in spufs caused get_event to succeed only once * on the ibox file, so we try it twice here */ spe_program_handle_t *binary; speid_t spe_thread; spe_gid_t spe_group; const uint32_t mbox_magic = 0xDEAD4EAD; uint32_t mbox_data; int status; int ret; static int test_result __attribute__ ((aligned(128))); binary = spe_open_image("spe-test-ibox2"); if (!binary) { perror("spe_open_image"); return 1; } spe_group = spe_create_group(SCHED_OTHER, 0, 0); if (!spe_group) { perror("spe_create_group"); return 2; } spe_thread = spe_create_thread(spe_group, binary, &test_result, NULL, 0xffff, 0); if (!spe_thread) { perror("spe_create_thread"); return 3; } ret = ppe_test_read_ibox(spe_group, spe_thread, &mbox_data); if (ret) return 5; ret = spe_write_in_mbox (spe_thread, mbox_magic); if (ret) { perror("spe_write_in_mbox1"); return 6; } ret = ppe_test_read_ibox(spe_group, spe_thread, &mbox_data); if (ret) return 7; ret = spe_write_in_mbox (spe_thread, mbox_magic); if (ret) { perror("spe_write_in_mbox2"); return 8; } ret = spe_wait(spe_thread, &status, 0); if (ret) { perror("spe_wait"); return 9; } return 0; } #endif static int ppe_dma_test(int (*fn)(speid_t, spe_gid_t, uint32_t, void*)) { spe_program_handle_t *binary; speid_t spe_thread; spe_gid_t spe_group; const uint32_t mbox_magic = 0xDEAD4EAD; uint32_t ls_offs; void *ls_buf; int status; int ret; static int test_result __attribute__ ((aligned(128))); binary = spe_open_image("spe-test-ppedma"); if (!binary) { perror("spe_open_image"); return 1; } spe_group = spe_create_group(SCHED_OTHER, 0, 0); if (!spe_group) { perror("spe_create_group"); return 2; } spe_thread = spe_create_thread(spe_group, binary, &test_result, NULL, 0xffff, 0); if (!spe_thread) { perror("spe_create_thread"); return 3; } ls_buf = spe_get_ls(spe_thread); if (!ls_buf) { perror("spe_get_ls"); return 4; } ret = ppe_test_read_ibox(spe_group, spe_thread, &ls_offs); if (ret) return 5; ls_buf += ls_offs; ret = fn(spe_thread, spe_group, ls_offs, ls_buf); if (ret) return ret; ret = spe_write_in_mbox (spe_thread, mbox_magic); if (ret) { perror("spe_write_in_mbox"); return 9; } ret = spe_wait(spe_thread, &status, 0); if (ret) { perror("spe_wait"); return 10; } return 0; } static int do_ppe_dma_put(speid_t t, spe_gid_t g, uint32_t ls_offs, void *ls_buf) { static const int size = 16 * 1024; static int buf[size / sizeof(int)] __attribute__((aligned(128))); int ret; struct spe_event e = { .gid = g, .events = SPE_EVENT_TAG_GROUP, }; memset(ls_buf, 0, size); memset(buf, 0x5a, size); ret = spe_mfc_put(t, ls_offs, buf, size, 1, 0, 0); if (ret) { perror("do_ppe_dma_put: spe_mfc_put"); return 9; } ret = spe_get_event(&e, 1, 1000); if (!ret) { fprintf(stderr, "do_ppe_dma_put: spe_get_event: timeout\n"); // return 7; } if (memcmp(buf, ls_buf, size) != 0) { fprintf(stderr, "do_ppe_dma_put: miscompare\n"); return 10; } return 0; } static int ppe_dma_put(void) { return ppe_dma_test(do_ppe_dma_put); } static int do_ppe_dma_get(speid_t t, spe_gid_t g, uint32_t ls_offs, void *ls_buf) { static const int size = 16 * 1024; static int buf[size / sizeof(int)] __attribute__((aligned(128))); int ret; struct spe_event e = { .gid = g, .events = SPE_EVENT_TAG_GROUP, }; memset(ls_buf, 0, size); memset(buf, 0x5a, size); ret = spe_mfc_get(t, ls_offs, buf, size, 1, 0, 0); if (ret) { perror("do_ppe_dma_get: spe_mfc_get"); return 9; } ret = spe_get_event(&e, 1, 1000); if (!ret) { fprintf(stderr, "do_ppe_dma_get: spe_get_event: timeout\n"); // return 7; } if (memcmp(buf, ls_buf, size) != 0) { fprintf(stderr, "do_ppe_dma_get: miscompare\n"); return 10; } return 0; } static int ppe_dma_get(void) { return ppe_dma_test(do_ppe_dma_get); } static int do_ppe_dma_mput(speid_t t, spe_gid_t g, uint32_t ls_offs, void *ls_buf) { static const int size = 64 * 1024; static const int fragment = 512; static int buf[size / sizeof(int) * 4] __attribute__((aligned(128))); int ret; struct spe_event e = { .gid = g, .events = SPE_EVENT_TAG_GROUP, }; int i; memset(ls_buf, 0xaa, size); // memset(buf, 0x5a, size); for (i = 0; i < size/(fragment); i++) { ret = spe_mfc_put(t, ls_offs + fragment*i, (void*) buf + fragment *i, fragment, 1, 0, 0); if (ret) { perror("do_ppe_dma_mput: spe_mfc_get"); fprintf(stderr, "count %d\n", i); return 9; } } ret = spe_get_event(&e, 1, 1000); if (!ret) { fprintf(stderr, "do_ppe_dma_mput: spe_get_event: timeout\n"); // return 7; } if (memcmp(buf, ls_buf, size) != 0) { fprintf(stderr, "do_ppe_dma_mput: miscompare\n"); return 10; } return 0; } static int ppe_dma_mput(void) { return ppe_dma_test(do_ppe_dma_mput); } static struct { int (*fn)(void); const char *name; } tests[] = { { basic_test, "basic", }, { ppe_mbox_test, "mbox", }, { ppe_ibox_test, "ibox", }, /* { ppe_ibox2_test, "ibox2", }, */ { ppe_dma_get, "ppeget", }, { ppe_dma_put, "ppeput", }, { ppe_dma_mput, "ppemput", }, }; static const int num_tests = sizeof (tests) / sizeof (tests[0]); int runtest(char *name) { int i, ret; ret = 0; for (i = 0; i < num_tests; i++) { if (strcmp(tests[i].name, name) == 0) { fprintf(stderr, "%02d: %s\n", i, tests[i].name); ret = tests[i].fn(); fprintf(stderr, "%02d: return: %d\n", i, ret); break; } } return ret; } int runalltests(void) { int i, ret; for (i = 0; i < num_tests; i++) { fprintf(stderr, "%02d: %s\n", i, tests[i].name); ret = tests[i].fn(); fprintf(stderr, "%02d: return: %d\n", i, ret); if (ret) break; } return ret; } int main(int argc, char *argv[]) { int i; int ret; ret = 0; if (argc == 1) ret = runalltests(); else for (i = 1; i < argc; i++) { ret = runtest(argv[i]); if (ret) break; } return ret; } libspe-1.2.2/tests/ft/spe-test-event.c0000640000076400007640000000244510533602311017363 0ustar cellbldcellbld/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include int main(void) { int i,j,a[128]; for(i=0; i< 1500000 ; i++) { for(j=0; j< 128; j++) { a[j] += i; } } si_stop(0x1199); for(i=0; i< 1500000 ; i++) { for(j=0; j< 128; j++) { a[j] += i; } } // spu_writech(mfc_wr_intr_mailbox, 0xaabd); spu_writech(SPU_WrOutIntrMbox, 0xaabd); for(i=0; i< 1500000 ; i++) { for(j=0; j< 128; j++) { a[j] += i; } } si_stop(0x119A); return 0; } libspe-1.2.2/tests/ft/spe-test-pause.c0000640000076400007640000000177510533602311017364 0ustar cellbldcellbld/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include int main(void) { int i,j,a[128]; for(i=0; i< 1500000 ; i++) { for(j=0; j< 128; j++) { a[j] += i; } } return 0; } libspe-1.2.2/tests/ft/spe-test-mboxwait.c0000640000076400007640000000176110533602311020074 0ustar cellbldcellbld/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include int main(void) { unsigned int data; data = spu_readch(SPU_RdInMbox); spu_writech(SPU_WrOutMbox, data); return 0; } libspe-1.2.2/tests/ft/spe-test-ppedma.c0000640000076400007640000000214610533602311017506 0ustar cellbldcellbld/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include int main(void) { unsigned int data; void *space; space = malloc(64 * 1024); spu_writech(SPU_WrOutIntrMbox, (unsigned long) space); /* wait for signal to finish */ data = spu_readch(SPU_RdInMbox); return 0; } libspe-1.2.2/tests/ft/spe-test-start-stop.c0000640000076400007640000000162610533602311020362 0ustar cellbldcellbld/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include int main(void) { return 0; } libspe-1.2.2/tests/ft/spe-test-block.c0000640000076400007640000000177710533602311017343 0ustar cellbldcellbld/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include int main(void) { int i,j,a[128]; for(i=0; i< 150000000 ; i++) { for(j=0; j< 128; j++) { a[j] += i; } } return 0; } libspe-1.2.2/tests/ft/spe-test-mbox-block.c0000640000076400007640000000207410533602311020275 0ustar cellbldcellbld/* * libspe - A wrapper library to adapt the JSRE SPU usage model to SPUFS * Copyright (C) 2005 IBM Corp. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include int main(void) { unsigned int data = 0xaabb; spu_writech(SPU_WrOutIntrMbox, data); si_stop(0x1188); data = 0xccdd; spu_writech(SPU_WrOutIntrMbox, data); si_stop(0x1189); return 0; } libspe-1.2.2/tests/ft/spe-test-dma-write.c0000640000076400007640000000104710533602311020130 0ustar cellbldcellbld#include "spu_intrinsics.h" typedef union { unsigned long long ull; unsigned int vp[2]; } addr64; int result __attribute__ ((aligned (128))); int main ( int spuid, addr64 argp, addr64 envp) { unsigned long long argAddress = argp.ull; /* Write to specified address */ result = 42; spu_mfcdma32 (&result, argAddress, 4, 0, (((0) << 24) | ((0) << 16) | (0x20) )); __builtin_si_wrch((22),__builtin_si_from_uint(1)); spu_mfcstat(0x2); /* Done */ return 0; } libspe-1.2.2/tools/0000755000076400007640000000000010575455116013737 5ustar cellbldcellbldlibspe-1.2.2/tools/README0000640000076400007640000000015110533602312014572 0ustar cellbldcellbldContents of this Directory elfspe-register: Script to register a SPE-ELF loading app with binfmt_misc. libspe-1.2.2/tools/elfspe-register0000750000076400007640000000036510533602312016746 0ustar cellbldcellbld#!/bin/sh if test -f /proc/sys/fs/binfmt_misc/spe then echo "elfspe already registered" else echo ':spe:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x17::/usr/bin/elfspe:' \ >/proc/sys/fs/binfmt_misc/register fi