summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--COPYING502
-rw-r--r--backend/CMakeLists.txt104
-rw-r--r--backend/src/CMakeLists.txt42
-rw-r--r--backend/src/ir/function.cpp19
-rw-r--r--backend/src/ir/function.hpp19
-rw-r--r--backend/src/ir/instruction.cpp19
-rw-r--r--backend/src/ir/instruction.hpp19
-rw-r--r--backend/src/ir/register.cpp19
-rw-r--r--backend/src/ir/register.hpp19
-rw-r--r--backend/src/ir/scope.cpp19
-rw-r--r--backend/src/ir/scope.hpp19
-rw-r--r--backend/src/ir/unit.cpp19
-rw-r--r--backend/src/ir/unit.hpp19
-rw-r--r--backend/src/sys/alloc.cpp261
-rw-r--r--backend/src/sys/alloc.hpp229
-rw-r--r--backend/src/sys/array.hpp108
-rw-r--r--backend/src/sys/atomic.hpp57
-rw-r--r--backend/src/sys/barrier.hpp62
-rw-r--r--backend/src/sys/condition.cpp139
-rw-r--r--backend/src/sys/condition.hpp40
-rw-r--r--backend/src/sys/constants.hpp144
-rw-r--r--backend/src/sys/default_path.cpp38
-rw-r--r--backend/src/sys/default_path.hpp34
-rw-r--r--backend/src/sys/filename.cpp123
-rw-r--r--backend/src/sys/filename.hpp72
-rw-r--r--backend/src/sys/fixed_array.hpp79
-rw-r--r--backend/src/sys/hash_map.hpp73
-rw-r--r--backend/src/sys/intrinsics.hpp210
-rw-r--r--backend/src/sys/library.cpp91
-rw-r--r--backend/src/sys/library.hpp40
-rw-r--r--backend/src/sys/list.hpp60
-rw-r--r--backend/src/sys/logging.cpp87
-rw-r--r--backend/src/sys/logging.hpp141
-rw-r--r--backend/src/sys/map.hpp63
-rw-r--r--backend/src/sys/mutex.cpp49
-rw-r--r--backend/src/sys/mutex.hpp75
-rw-r--r--backend/src/sys/platform.cpp79
-rw-r--r--backend/src/sys/platform.hpp373
-rw-r--r--backend/src/sys/ref.hpp99
-rw-r--r--backend/src/sys/set.hpp59
-rw-r--r--backend/src/sys/string.cpp130
-rw-r--r--backend/src/sys/string.hpp53
-rw-r--r--backend/src/sys/sysinfo.cpp148
-rw-r--r--backend/src/sys/sysinfo.hpp37
-rw-r--r--backend/src/sys/thread.cpp213
-rw-r--r--backend/src/sys/thread.hpp54
-rw-r--r--backend/src/sys/vector.hpp72
-rw-r--r--backend/src/utest/utest.cpp57
-rw-r--r--backend/src/utest/utest.hpp53
-rw-r--r--backend/src/utest/utest_console.cpp95
-rw-r--r--backend/src/utest/utest_font.cpp41
-rw-r--r--backend/src/utest/utest_lua.cpp58
-rw-r--r--backend/src/utest/utest_rt.cpp193
-rw-r--r--backend/src/utest/utest_tasking.cpp653
54 files changed, 5580 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 00000000..4362b491
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,502 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, 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.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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 Street, 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.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt
new file mode 100644
index 00000000..73a79edb
--- /dev/null
+++ b/backend/CMakeLists.txt
@@ -0,0 +1,104 @@
+project (PF)
+
+cmake_minimum_required (VERSION 2.6.0)
+
+set (PF_CMAKE_DIR "${PF_SOURCE_DIR}/cmake")
+set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PF_CMAKE_DIR}")
+
+##############################################################
+# Compilation directives
+##############################################################
+
+set (PF_DEBUG_MEMORY false CACHE bool "Activate the memory debugger")
+set (PF_USE_BLOB false CACHE bool "Compile everything from one big file")
+set (PF_VERBOSE_VECTORIZER false CACHE bool "Output vectorizer diagnostic (GCC only)")
+
+##############################################################
+# Compiler
+##############################################################
+if (UNIX)
+ set (COMPILER "GCC" CACHE INT "Compiler to choose on Linux (GCC,ICC,CLANG)")
+endif (UNIX)
+
+if (WIN32)
+ if (MINGW)
+ set (DEF "-D")
+ else (MINGW)
+ set (DEF "/D")
+ endif (MINGW)
+else (WIN32)
+ set (DEF "-D")
+endif (WIN32)
+
+if (PF_DEBUG_MEMORY)
+ set (PF_DEBUG_MEMORY_FLAG "${DEF}PF_DEBUG_MEMORY=1")
+else (PF_DEBUG_MEMORY)
+ set (PF_DEBUG_MEMORY_FLAG "${DEF}PF_DEBUG_MEMORY=0")
+endif (PF_DEBUG_MEMORY)
+
+## Linux compilation
+if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ # Hide all symbols and allows the symbols declared as visible to be exported
+ set (VISIBILITY_FLAG "-fvisibility=hidden")
+
+ if (COMPILER STREQUAL "GCC")
+ set (CMAKE_CXX_FLAGS "-Wstrict-aliasing=2 -Wno-invalid-offsetof -fstrict-aliasing -msse2 -ffast-math -fPIC -Wall -fno-rtti -std=c++0x")
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PF_DEBUG_MEMORY_FLAG}")
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${VISIBILITY_FLAG} -Wl,-E")
+ set (CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG -ftree-vectorize")
+ if (PF_VERBOSE_VECTORIZER)
+ set (CMAKE_CXX_FLAGS "-ftree-vectorizer-verbose=2")
+ endif (PF_VERBOSE_VECTORIZER)
+ elseif (COMPILER STREQUAL "CLANG")
+ set (CMAKE_C_COMPILER "clang")
+ set (CMAKE_C_FLAGS "-Wall -std=c99")
+ set (CMAKE_C_FLAGS_DEBUG "-g")
+ set (CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG")
+ set (CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG")
+ set (CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g")
+ set (CMAKE_CXX_COMPILER "clang++")
+ set (CMAKE_CXX_FLAGS "-fstrict-aliasing -msse2 -ffast-math -fPIC -Wall -Wno-format-security -Wno-invalid-offsetof -std=c++0x")
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PF_DEBUG_MEMORY_FLAG}")
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${VISIBILITY_FLAG}")
+ set (CMAKE_CXX_FLAGS_DEBUG "-g")
+ set (CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG")
+ set (CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")
+ set (CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")
+ set (CMAKE_AR "/usr/bin/llvm-ar")
+ set (CMAKE_LINKER "/usr/bin/llvm-ld")
+ set (CMAKE_NM "/usr/bin/llvm-nm")
+ set (CMAKE_OBJDUMP "/usr/bin/llvm-objdump")
+ set (CMAKE_RANLIB "ranlib")
+ elseif (COMPILER STREQUAL "ICC")
+ set (CMAKE_CXX_COMPILER "icpc")
+ set (CMAKE_C_COMPILER "icc")
+ set (CMAKE_CXX_FLAGS "-std=c++0x -wd2928 -Wall -fPIC -fstrict-aliasing -fp-model fast -xSSE2")
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PF_DEBUG_MEMORY_FLAG}")
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${VISIBILITY_FLAG} -Wl,-E")
+ set (CMAKE_CXX_FLAGS_DEBUG "-g -O0")
+ set (CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O2")
+ set (CCMAKE_CXX_FLAGS_RELWITHDEBINFO "-g -O2")
+ set (CCMAKE_CXX_FLAGS_MINSIZEREL "-Os")
+ set (CMAKE_EXE_LINKER_FLAGS "")
+ endif ()
+
+## Windows compilation
+elseif (CMAKE_SYSTEM_NAME STREQUAL "Windows")
+ if (MINGW)
+ if (PF_VERBOSE_VECTORIZER)
+ set (CMAKE_CXX_FLAGS "-ftree-vectorizer-verbose=2")
+ endif (PF_VERBOSE_VECTORIZER)
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PF_DEBUG_MEMORY_FLAG} -Wno-invalid-offsetof -fstrict-aliasing -msse2 -ffast-math -Wall -fno-rtti -std=c++0x")
+ set (CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
+ else (MINGW)
+ set (COMMON_FLAGS "${PF_DEBUG_MEMORY_FLAG} /arch:SSE2 /D_CRT_SECURE_NO_WARNINGS /DNOMINMAX /GR- /GS- /W3 /wd4275")
+ set (CMAKE_CXX_FLAGS ${COMMON_FLAGS})
+ set (CMAKE_C_FLAGS ${COMMON_FLAGS})
+ endif (MINGW)
+endif ()
+
+##############################################################
+# Project source code
+##############################################################
+add_subdirectory (src)
+
diff --git a/backend/src/CMakeLists.txt b/backend/src/CMakeLists.txt
new file mode 100644
index 00000000..5a3b20b6
--- /dev/null
+++ b/backend/src/CMakeLists.txt
@@ -0,0 +1,42 @@
+set (GBE_SRC
+ sys/vector.hpp
+ sys/hash_map.hpp
+ sys/map.hpp
+ sys/string.cpp
+ sys/string.hpp
+ sys/filename.cpp
+ sys/filename.hpp
+ sys/library.cpp
+ sys/library.hpp
+ sys/thread.cpp
+ sys/thread.hpp
+ sys/alloc.cpp
+ sys/alloc.hpp
+ sys/sysinfo.cpp
+ sys/sysinfo.hpp
+ sys/ref.hpp
+ sys/mutex.cpp
+ sys/mutex.hpp
+ sys/condition.cpp
+ sys/condition.hpp
+ sys/platform.cpp
+ sys/platform.hpp
+ sys/logging.cpp
+ sys/logging.hpp
+ sys/default_path.cpp
+ sys/default_path.hpp)
+
+set (COMPILE_UTEST false CACHE bool "Compile or not the unit tests")
+if (COMPILE_UTEST)
+ set (GBE_SRC ${GBE_SRC})
+endif (COMPILE_UTEST)
+
+if (UNIX)
+ set (EXEC_DEPENDENCIES pthread dl)
+else (UNIX)
+ set (EXEC_DEPENDENCIES)
+endif (UNIX)
+
+include_directories (.)
+add_library (gbe SHARED ${GBE_SRC})
+
diff --git a/backend/src/ir/function.cpp b/backend/src/ir/function.cpp
new file mode 100644
index 00000000..12001d60
--- /dev/null
+++ b/backend/src/ir/function.cpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
diff --git a/backend/src/ir/function.hpp b/backend/src/ir/function.hpp
new file mode 100644
index 00000000..12001d60
--- /dev/null
+++ b/backend/src/ir/function.hpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
diff --git a/backend/src/ir/instruction.cpp b/backend/src/ir/instruction.cpp
new file mode 100644
index 00000000..12001d60
--- /dev/null
+++ b/backend/src/ir/instruction.cpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
diff --git a/backend/src/ir/instruction.hpp b/backend/src/ir/instruction.hpp
new file mode 100644
index 00000000..12001d60
--- /dev/null
+++ b/backend/src/ir/instruction.hpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
diff --git a/backend/src/ir/register.cpp b/backend/src/ir/register.cpp
new file mode 100644
index 00000000..12001d60
--- /dev/null
+++ b/backend/src/ir/register.cpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
diff --git a/backend/src/ir/register.hpp b/backend/src/ir/register.hpp
new file mode 100644
index 00000000..12001d60
--- /dev/null
+++ b/backend/src/ir/register.hpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
diff --git a/backend/src/ir/scope.cpp b/backend/src/ir/scope.cpp
new file mode 100644
index 00000000..12001d60
--- /dev/null
+++ b/backend/src/ir/scope.cpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
diff --git a/backend/src/ir/scope.hpp b/backend/src/ir/scope.hpp
new file mode 100644
index 00000000..12001d60
--- /dev/null
+++ b/backend/src/ir/scope.hpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
diff --git a/backend/src/ir/unit.cpp b/backend/src/ir/unit.cpp
new file mode 100644
index 00000000..12001d60
--- /dev/null
+++ b/backend/src/ir/unit.cpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
diff --git a/backend/src/ir/unit.hpp b/backend/src/ir/unit.hpp
new file mode 100644
index 00000000..12001d60
--- /dev/null
+++ b/backend/src/ir/unit.hpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
diff --git a/backend/src/sys/alloc.cpp b/backend/src/sys/alloc.cpp
new file mode 100644
index 00000000..e23ae8e6
--- /dev/null
+++ b/backend/src/sys/alloc.cpp
@@ -0,0 +1,261 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "sys/alloc.hpp"
+#include "sys/atomic.hpp"
+#include "sys/mutex.hpp"
+
+#if PF_DEBUG_MEMORY
+#ifdef __MSVC__
+#include <unordered_map>
+#else
+#include <tr1/unordered_map>
+#endif /* __MSVC__ */
+#include <cstring>
+#endif /* PF_DEBUG_MEMORY */
+
+#if defined(__ICC__)
+#include <stdint.h>
+#endif /* __ICC__ */
+#include <map>
+#include <vector>
+
+////////////////////////////////////////////////////////////////////////////////
+/// Memory debugger
+////////////////////////////////////////////////////////////////////////////////
+namespace pf
+{
+
+#if PF_DEBUG_MEMORY
+ /*! Store each allocation data */
+ struct AllocData {
+ INLINE AllocData(void) {}
+ INLINE AllocData(int fileName_, int functionName_, int line_, intptr_t alloc_) :
+ fileName(fileName_), functionName(functionName_), line(line_), alloc(alloc_) {}
+ int fileName, functionName, line;
+ intptr_t alloc;
+ };
+
+ /*! Store allocation information */
+ struct MemDebugger {
+ MemDebugger(void) : unfreedNum(0), allocNum(0) {}
+ void* insertAlloc(void *ptr, const char *file, const char *function, int line);
+ void removeAlloc(void *ptr);
+ void dumpAlloc(void);
+ void dumpData(const AllocData &data);
+ /*! Count the still unfreed allocations */
+ volatile intptr_t unfreedNum;
+ /*! Total number of allocations done */
+ volatile intptr_t allocNum;
+ /*! Sorts the file name and function name strings */
+ std::tr1::unordered_map<const char*, int> staticStringMap;
+ /*! Each element contains the actual string */
+ std::vector<const char*> staticStringVector;
+ std::map<uintptr_t, AllocData> allocMap;
+ /*! Protect the memory debugger accesses */
+ MutexSys mutex;
+ };
+
+ void* MemDebugger::insertAlloc(void *ptr, const char *file, const char *function, int line)
+ {
+ if (ptr == NULL) return ptr;
+ Lock<MutexSys> lock(mutex);
+ const uintptr_t iptr = (uintptr_t) ptr;
+ if (UNLIKELY(allocMap.find(iptr) != allocMap.end())) {
+ this->dumpData(allocMap.find(iptr)->second);
+ FATAL("Pointer already in map");
+ }
+ const auto fileIt = staticStringMap.find(file);
+ const auto functionIt = staticStringMap.find(function);
+ int fileName, functionName;
+ if (fileIt == staticStringMap.end()) {
+ staticStringVector.push_back(file);
+ staticStringMap[file] = fileName = int(staticStringVector.size()) - 1;
+ } else
+ fileName = staticStringMap[file];
+ if (functionIt == staticStringMap.end()) {
+ staticStringVector.push_back(function);
+ staticStringMap[function] = functionName = int(staticStringVector.size()) - 1;
+ } else
+ functionName = staticStringMap[function];
+ allocMap[iptr] = AllocData(fileName, functionName, line, allocNum);
+ unfreedNum++;
+ allocNum++;
+ return ptr;
+ }
+
+ void MemDebugger::removeAlloc(void *ptr)
+ {
+ if (ptr == NULL) return;
+ Lock<MutexSys> lock(mutex);
+ const uintptr_t iptr = (uintptr_t) ptr;
+ FATAL_IF(allocMap.find(iptr) == allocMap.end(), "Pointer not referenced");
+ //if(allocMap.find(iptr) == allocMap.end()) debugbreak();
+ allocMap.erase(iptr);
+ unfreedNum--;
+ }
+
+ void MemDebugger::dumpData(const AllocData &data) {
+ std::cerr << "ALLOC " << data.alloc << ": " <<
+ "file " << staticStringVector[data.fileName] << ", " <<
+ "function " << staticStringVector[data.functionName] << ", " <<
+ "line " << data.line << std::endl;
+ }
+
+ void MemDebugger::dumpAlloc(void) {
+ std::cerr << "MemDebugger: Unfreed number: " << unfreedNum << std::endl;
+ for (auto it = allocMap.begin(); it != allocMap.end(); ++it)
+ this->dumpData(it->second);
+ std::cerr << "MemDebugger: " << staticStringVector.size()
+ << " allocated static strings" << std::endl;
+ }
+
+ /*! The user can deactivate the memory initialization */
+ static bool memoryInitializationEnabled = true;
+
+ /*! Declare C like interface functions here */
+ static MemDebugger *memDebugger = NULL;
+ void* MemDebuggerInsertAlloc(void *ptr, const char *file, const char *function, int line) {
+ if (memDebugger) return memDebugger->insertAlloc(ptr, file, function, line);
+ return ptr;
+ }
+ void MemDebuggerRemoveAlloc(void *ptr) {
+ if (memDebugger) memDebugger->removeAlloc(ptr);
+ }
+ void MemDebuggerDumpAlloc(void) {
+ if (memDebugger) memDebugger->dumpAlloc();
+ }
+ void MemDebuggerEnableMemoryInitialization(bool enabled) {
+ memoryInitializationEnabled = enabled;
+ }
+ void MemDebuggerInitializeMem(void *mem, size_t sz) {
+ if (memoryInitializationEnabled) std::memset(mem, 0xcd, sz);
+ }
+ void MemDebuggerStart(void) {
+ if (memDebugger) MemDebuggerEnd();
+ memDebugger = new MemDebugger;
+ }
+ void MemDebuggerEnd(void) {
+ MemDebugger *_debug = memDebugger;
+ memDebugger = NULL;
+ delete _debug;
+ }
+#endif /* PF_DEBUG_MEMORY */
+}
+
+namespace pf
+{
+ void* malloc(size_t size) {
+ void *ptr = std::malloc(size);
+ MemDebuggerInitializeMem(ptr, size);
+ return ptr;
+ }
+
+ void* realloc(void *ptr, size_t size) {
+#if PF_DEBUG_MEMORY
+ if (ptr) MemDebuggerRemoveAlloc(ptr);
+#endif /* PF_DEBUG_MEMORY */
+ PF_ASSERT(size);
+ if (ptr == NULL) {
+ ptr = std::realloc(ptr, size);
+ MemDebuggerInitializeMem(ptr, size);
+ return ptr;
+ } else
+ return std::realloc(ptr, size);
+ }
+
+ void free(void *ptr) { if (ptr != NULL) std::free(ptr); }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// Windows Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __WIN32__
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+namespace pf
+{
+ void* alignedMalloc(size_t size, size_t align) {
+ void* ptr = _mm_malloc(size,align);
+ FATAL_IF (!ptr && size, "memory allocation failed");
+ MemDebuggerInitializeMem(ptr, size);
+ return ptr;
+ }
+
+ void alignedFree(void *ptr) { _mm_free(ptr); }
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// Linux Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __LINUX__
+
+#include <unistd.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <malloc.h>
+#include <iostream>
+
+namespace pf
+{
+ void* alignedMalloc(size_t size, size_t align) {
+ void* ptr = memalign(align,size);
+ FATAL_IF (!ptr && size, "memory allocation failed");
+ MemDebuggerInitializeMem(ptr, size);
+ return ptr;
+ }
+
+ void alignedFree(void *ptr) { free(ptr); }
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// MacOS Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __MACOSX__
+
+#include <cstdlib>
+
+namespace pf
+{
+ void* alignedMalloc(size_t size, size_t align) {
+ void* mem = malloc(size+(align-1)+sizeof(void*));
+ FATAL_IF (!mem && size, "memory allocation failed");
+ char* aligned = ((char*)mem) + sizeof(void*);
+ aligned += align - ((uintptr_t)aligned & (align - 1));
+ ((void**)aligned)[-1] = mem;
+ MemDebuggerInitializeMem(aligned, size);
+ return aligned;
+ }
+
+ void alignedFree(void* ptr) {
+ PF_ASSERT(ptr);
+ free(((void**)ptr)[-1]);
+ }
+}
+
+#endif
+
diff --git a/backend/src/sys/alloc.hpp b/backend/src/sys/alloc.hpp
new file mode 100644
index 00000000..5b686343
--- /dev/null
+++ b/backend/src/sys/alloc.hpp
@@ -0,0 +1,229 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_ALLOC_HPP__
+#define __PF_ALLOC_HPP__
+
+#include "sys/platform.hpp"
+#include <cstdlib>
+#include <new>
+
+namespace pf
+{
+ /*! regular allocation */
+ void* malloc(size_t size);
+ void* realloc(void *ptr, size_t size);
+ void free(void *ptr);
+
+ /*! Aligned allocation */
+ void* alignedMalloc(size_t size, size_t align = 64);
+ void alignedFree(void* ptr);
+
+ /*! Monitor memory allocations */
+#if PF_DEBUG_MEMORY
+ void* MemDebuggerInsertAlloc(void*, const char*, const char*, int);
+ void MemDebuggerRemoveAlloc(void *ptr);
+ void MemDebuggerDumpAlloc(void);
+ void MemDebuggerInitializeMem(void *mem, size_t sz);
+ void MemDebuggerEnableMemoryInitialization(bool enabled);
+ void MemDebuggerStart(void);
+ void MemDebuggerEnd(void);
+#else
+ INLINE void* MemDebuggerInsertAlloc(void *ptr, const char*, const char*, int) {return ptr;}
+ INLINE void MemDebuggerRemoveAlloc(void *ptr) {}
+ INLINE void MemDebuggerDumpAlloc(void) {}
+ INLINE void MemDebuggerInitializeMem(void *mem, size_t sz) {}
+ INLINE void MemDebuggerEnableMemoryInitialization(bool enabled) {}
+ INLINE void MemDebuggerStart(void) {}
+ INLINE void MemDebuggerEnd(void) {}
+#endif /* PF_DEBUG_MEMORY */
+
+ /*! Properly handle the allocated type */
+ template <typename T>
+ T* _MemDebuggerInsertAlloc(T *ptr, const char *file, const char *function, int line) {
+ MemDebuggerInsertAlloc(ptr, file, function, line);
+ return ptr;
+ }
+} /* namespace pf */
+
+/*! Declare a structure with custom allocators */
+#define PF_STRUCT(TYPE) \
+ void* operator new(size_t size) { \
+ if (AlignOf<TYPE>::value > sizeof(uintptr_t)) \
+ return pf::alignedMalloc(size, AlignOf<TYPE>::value); \
+ else \
+ return pf::malloc(size); \
+ } \
+ void* operator new[](size_t size) { \
+ if (AlignOf<TYPE>::value > sizeof(uintptr_t)) \
+ return pf::alignedMalloc(size, AlignOf<TYPE>::value); \
+ else \
+ return pf::malloc(size); \
+ } \
+ void operator delete(void* ptr) { \
+ if (AlignOf<TYPE>::value > sizeof(uintptr_t)) \
+ return pf::alignedFree(ptr); \
+ else \
+ return pf::free(ptr); \
+ } \
+ void operator delete[](void* ptr) { \
+ if (AlignOf<TYPE>::value > sizeof(uintptr_t)) \
+ return pf::alignedFree(ptr); \
+ else \
+ return pf::free(ptr); \
+ } \
+
+/*! Declare a class with custom allocators */
+#define PF_CLASS(TYPE) \
+public: \
+ PF_STRUCT(TYPE) \
+private:
+
+/*! Declare an aligned structure */
+#define PF_ALIGNED_STRUCT(ALIGN) \
+ void* operator new(size_t size) { return pf::alignedMalloc(size, ALIGN); }\
+ void* operator new[](size_t size) { return pf::alignedMalloc(size, ALIGN); }\
+ void operator delete(void* ptr) { pf::alignedFree(ptr); } \
+ void operator delete[](void* ptr) { pf::alignedFree(ptr); }
+
+/*! Declare an aligned class */
+#define PF_ALIGNED_CLASS(ALIGN) \
+public: \
+ PF_ALIGNED_STRUCT(ALIGN) \
+private:
+
+/*! Macros to handle allocation position */
+#define PF_NEW(T,...) \
+ pf::_MemDebuggerInsertAlloc(new T(__VA_ARGS__), __FILE__, __FUNCTION__, __LINE__)
+
+#define PF_NEW_ARRAY(T,N,...) \
+ pf::_MemDebuggerInsertAlloc(new T[N](__VA_ARGS__), __FILE__, __FUNCTION__, __LINE__)
+
+#define PF_NEW_P(T,X,...) \
+ pf::_MemDebuggerInsertAlloc(new (X) T(__VA_ARGS__), __FILE__, __FUNCTION__, __LINE__)
+
+#define PF_DELETE(X) \
+ do { pf::MemDebuggerRemoveAlloc(X); delete X; } while (0)
+
+#define PF_DELETE_ARRAY(X) \
+ do { pf::MemDebuggerRemoveAlloc(X); delete[] X; } while (0)
+
+#define PF_MALLOC(SZ) \
+ pf::MemDebuggerInsertAlloc(pf::malloc(SZ),__FILE__, __FUNCTION__, __LINE__)
+
+#define PF_REALLOC(PTR, SZ) \
+ pf::MemDebuggerInsertAlloc(pf::realloc(PTR, SZ),__FILE__, __FUNCTION__, __LINE__)
+
+#define PF_FREE(X) \
+ do { pf::MemDebuggerRemoveAlloc(X); pf::free(X); } while (0)
+
+#define PF_ALIGNED_FREE(X) \
+ do { pf::MemDebuggerRemoveAlloc(X); pf::alignedFree(X); } while (0)
+
+#define PF_ALIGNED_MALLOC(SZ,ALIGN) \
+ pf::MemDebuggerInsertAlloc(pf::alignedMalloc(SZ,ALIGN),__FILE__, __FUNCTION__, __LINE__)
+
+namespace pf
+{
+ /*! STL compliant allocator to intercept all memory allocations */
+ template<typename T>
+ class Allocator {
+ public:
+ typedef T value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef typename std::allocator<void>::const_pointer void_allocator_ptr;
+ template<typename U>
+ struct rebind { typedef Allocator<U> other; };
+
+ INLINE Allocator(void) {}
+ INLINE ~Allocator(void) {}
+ INLINE Allocator(Allocator const&) {}
+ template<typename U>
+ INLINE Allocator(Allocator<U> const&) {}
+ INLINE pointer address(reference r) { return &r; }
+ INLINE const_pointer address(const_reference r) { return &r; }
+ INLINE pointer allocate(size_type n, void_allocator_ptr = 0) {
+ if (AlignOf<T>::value > sizeof(uintptr_t))
+ return (pointer) PF_ALIGNED_MALLOC(n*sizeof(T), AlignOf<T>::value);
+ else
+ return (pointer) PF_MALLOC(n * sizeof(T));
+ }
+ INLINE void deallocate(pointer p, size_type) {
+ if (AlignOf<T>::value > sizeof(uintptr_t))
+ PF_ALIGNED_FREE(p);
+ else
+ PF_FREE(p);
+ }
+ INLINE size_type max_size(void) const {
+ return std::numeric_limits<size_type>::max() / sizeof(T);
+ }
+ INLINE void construct(pointer p, const T& t = T()) { ::new(p) T(t); }
+ INLINE void destroy(pointer p) { p->~T(); }
+ INLINE bool operator==(Allocator const&) { return true; }
+ INLINE bool operator!=(Allocator const& a) { return !operator==(a); }
+ };
+
+ /*! A growing pool never deallocates */
+ template <typename T>
+ class GrowingPool
+ {
+ public:
+ GrowingPool(void) : current(PF_NEW(GrowingPoolElem, 1)) {}
+ ~GrowingPool(void) { PF_ASSERT(current); PF_DELETE(current); }
+ T *allocate(void) {
+ if (UNLIKELY(current->allocated == current->maxElemNum)) {
+ GrowingPoolElem *elem = PF_NEW(GrowingPoolElem, 2 * current->maxElemNum);
+ elem->next = current;
+ current = elem;
+ }
+ T *data = current->data + current->allocated++;
+ return data;
+ }
+ private:
+ /*! Chunk of elements to allocate */
+ class GrowingPoolElem
+ {
+ friend class GrowingPool;
+ GrowingPoolElem(size_t elemNum) {
+ this->data = PF_NEW_ARRAY(T, elemNum);
+ this->next = NULL;
+ this->maxElemNum = elemNum;
+ this->allocated = 0;
+ }
+ ~GrowingPoolElem(void) {
+ PF_ASSERT(this->data);
+ PF_DELETE_ARRAY(this->data);
+ if (this->next) PF_DELETE(this->next);
+ }
+ T *data;
+ GrowingPoolElem *next;
+ size_t allocated, maxElemNum;
+ };
+ GrowingPoolElem *current;
+ PF_CLASS(GrowingPool);
+ };
+} /* namespace pf */
+
+#endif /* __PF_ALLOC_HPP__ */
+
diff --git a/backend/src/sys/array.hpp b/backend/src/sys/array.hpp
new file mode 100644
index 00000000..04cc3c6c
--- /dev/null
+++ b/backend/src/sys/array.hpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_ARRAY_HPP__
+#define __PF_ARRAY_HPP__
+
+#include "sys/platform.hpp"
+#include <vector>
+
+namespace pf
+{
+ /*! Non resizable array with no checking. We make it non-copiable right now
+ * since we do not want to implement an expensive deep copy
+ */
+ template<class T>
+ class array
+ {
+ public:
+ /*! Create an empty array */
+ INLINE array(void) : elem(NULL), elemNum(0) {}
+ /*! Allocate an array with elemNum allocated elements */
+ INLINE array(size_t elemNum) : elem(NULL), elemNum(0) { this->resize(elemNum); }
+ /*! Copy constructor */
+ INLINE array(const array &other) {
+ this->elemNum = other.elemNum;
+ if (this->elemNum) {
+ this->elem = PF_NEW_ARRAY(T, this->elemNum);
+ for (size_t i = 0; i < this->elemNum; ++i) this->elem[i] = other.elem[i];
+ } else
+ this->elem = NULL;
+ }
+ /*! Assignment operator */
+ INLINE array& operator= (const array &other) {
+ if (this->elem != NULL && this->elemNum != other->elemNum) {
+ PF_DELETE_ARRAY(this->elem);
+ this->elem = NULL;
+ this->elemNum = 0;
+ }
+ this->elemNum = other.elemNum;
+ if (this->elemNum) {
+ if (this->elem == NULL)
+ this->elem = PF_NEW_ARRAY(T, this->elemNum);
+ for (size_t i = 0; i < this->elemNum; ++i) this->elem[i] = other.elem[i];
+ } else
+ this->elem = NULL;
+ return *this;
+ }
+ /*! Delete the allocated elements */
+ INLINE ~array(void) { PF_SAFE_DELETE_ARRAY(elem); }
+ /*! Free the already allocated elements and allocate a new array */
+ INLINE void resize(size_t elemNum_) {
+ if (elemNum_ != this->elemNum) {
+ PF_SAFE_DELETE_ARRAY(elem);
+ if (elemNum_)
+ this->elem = PF_NEW_ARRAY(T, elemNum_);
+ else
+ this->elem = NULL;
+ this->elemNum = elemNum_;
+ }
+ }
+ /*! Steal the pointer. The array becomes emtpy */
+ INLINE T *steal(void) {
+ T *stolen = this->elem;
+ this->elem = NULL;
+ this->elemNum = 0;
+ return stolen;
+ }
+ /*! First element */
+ INLINE T *begin(void) { return this->elem; }
+ /*! First non-valid element */
+ INLINE T *end(void) { return this->elem + elemNum; }
+ /*! Get element at position index (with a bound check) */
+ INLINE T &operator[] (size_t index) {
+ PF_ASSERT(elem && index < elemNum);
+ return elem[index];
+ }
+ /*! Get element at position index (with bound check) */
+ INLINE const T &operator[] (size_t index) const {
+ PF_ASSERT(elem && index < elemNum);
+ return elem[index];
+ }
+ /*! Return the number of elements */
+ INLINE size_t size(void) const { return this->elemNum; }
+ private:
+ T *elem; //!< Points to the elements
+ size_t elemNum; //!< Number of elements in the array
+ PF_CLASS(array);
+ };
+} /* namespace pf */
+
+#endif /* __PF_ARRAY_HPP__ */
+
diff --git a/backend/src/sys/atomic.hpp b/backend/src/sys/atomic.hpp
new file mode 100644
index 00000000..07b2fdaf
--- /dev/null
+++ b/backend/src/sys/atomic.hpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_ATOMIC_HPP__
+#define __PF_ATOMIC_HPP__
+
+#include "sys/intrinsics.hpp"
+
+namespace pf
+{
+ template <typename T>
+ struct AtomicInternal {
+ protected:
+ AtomicInternal(const AtomicInternal&); // don't implement
+ AtomicInternal& operator= (const AtomicInternal&); // don't implement
+
+ public:
+ INLINE AtomicInternal(void) {}
+ INLINE AtomicInternal(T data) : data(data) {}
+ INLINE AtomicInternal& operator =(const T input) { data = input; return *this; }
+ INLINE operator T() const { return data; }
+ INLINE void storeRelease(T x) { __store_release(&data, x); }
+ public:
+ INLINE friend T operator+= (AtomicInternal& value, T input) { return atomic_add(&value.data, input) + input; }
+ INLINE friend T operator++ (AtomicInternal& value) { return atomic_add(&value.data, 1) + 1; }
+ INLINE friend T operator-- (AtomicInternal& value) { return atomic_add(&value.data, -1) - 1; }
+ INLINE friend T operator++ (AtomicInternal& value, int) { return atomic_add(&value.data, 1); }
+ INLINE friend T operator-- (AtomicInternal& value, int) { return atomic_add(&value.data, -1); }
+ INLINE friend T cmpxchg (AtomicInternal& value, const T v, const T c) { return atomic_cmpxchg(&value.data,v,c); }
+
+ private:
+ volatile T data;
+ PF_STRUCT(AtomicInternal);
+ };
+
+ typedef AtomicInternal<atomic32_t> Atomic32;
+ typedef AtomicInternal<atomic_t> Atomic;
+}
+
+#endif /* __PF_ATOMIC_HPP__ */
+
diff --git a/backend/src/sys/barrier.hpp b/backend/src/sys/barrier.hpp
new file mode 100644
index 00000000..9182a98c
--- /dev/null
+++ b/backend/src/sys/barrier.hpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_BARRIER_H__
+#define __PF_BARRIER_H__
+
+#include "sys/condition.hpp"
+
+namespace pf
+{
+ /*! system barrier using operating system */
+ class BarrierSys
+ {
+ public:
+
+ void init(size_t count) {
+ this->count = 0;
+ this->full_size = count;
+ }
+
+ int wait() {
+ count_mutex.lock();
+ count++;
+ if (count == full_size) {
+ count = 0;
+ cond.broadcast();
+ count_mutex.unlock();
+ return 1;
+ }
+ cond.wait(count_mutex);
+ count_mutex.unlock();
+ return 0;
+ }
+
+ protected:
+ size_t count, full_size;
+ MutexSys count_mutex;
+ ConditionSys cond;
+ PF_CLASS(BarrierSys);
+ };
+
+ /* default barrier type */
+ class Barrier : public BarrierSys {};
+}
+
+#endif
diff --git a/backend/src/sys/condition.cpp b/backend/src/sys/condition.cpp
new file mode 100644
index 00000000..27923f22
--- /dev/null
+++ b/backend/src/sys/condition.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "sys/condition.hpp"
+
+#if defined(__WIN32__)
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#if defined(__GNUC__)
+
+namespace pf
+{
+ // This is an implementation of POSIX "compatible" condition variables for
+ // Win32, as described by Douglas C. Schmidt and Irfan Pyarali:
+ // http://www.cs.wustl.edu/~schmidt/win32-cv-1.html. The code is directly
+ // readapted from the glfw source code that may be found here:
+ // http://www.glfw.org
+ enum {
+ MINGW32_COND_SIGNAL = 0,
+ MINGW32_COND_BROADCAST = 1
+ };
+
+ /*! Implement the internal condition variable implementation Mingw lacks */
+ struct Mingw32Cond
+ {
+ HANDLE events[2]; //<! Signal and broadcast event HANDLEs
+ unsigned int waiters_count; //<! Count of the number of waiters
+ CRITICAL_SECTION waiters_count_lock;//!< Serialize access to <waiters_count>
+ };
+
+ ConditionSys::ConditionSys ()
+ {
+ cond = (Mingw32Cond *) PF_NEW(Mingw32Cond);
+ ((Mingw32Cond *)cond)->waiters_count = 0;
+ ((Mingw32Cond *)cond)->events[MINGW32_COND_SIGNAL] = CreateEvent(NULL, FALSE, FALSE, NULL);
+ ((Mingw32Cond *)cond)->events[MINGW32_COND_BROADCAST] = CreateEvent(NULL, TRUE, FALSE, NULL);
+ InitializeCriticalSection(&((Mingw32Cond *)cond)->waiters_count_lock);
+ }
+
+ ConditionSys::~ConditionSys ()
+ {
+ CloseHandle(((Mingw32Cond *)cond)->events[MINGW32_COND_SIGNAL]);
+ CloseHandle(((Mingw32Cond *)cond)->events[MINGW32_COND_BROADCAST]);
+ DeleteCriticalSection(&((Mingw32Cond *)cond)->waiters_count_lock);
+ PF_DELETE((Mingw32Cond *)cond);
+ }
+
+ void ConditionSys::wait(MutexSys& mutex)
+ {
+ Mingw32Cond *cv = (Mingw32Cond *) cond;
+ int result, last_waiter;
+ DWORD timeout_ms;
+
+ // Avoid race conditions
+ EnterCriticalSection(&cv->waiters_count_lock);
+ cv->waiters_count ++;
+ LeaveCriticalSection(&cv->waiters_count_lock);
+
+ // It's ok to release the mutex here since Win32 manual-reset events
+ // maintain state when used with SetEvent()
+ LeaveCriticalSection((CRITICAL_SECTION *) mutex.mutex);
+ timeout_ms = INFINITE;
+
+ // Wait for either event to become signaled
+ result = WaitForMultipleObjects(2, cv->events, FALSE, timeout_ms);
+
+ // Check if we are the last waiter
+ EnterCriticalSection(&cv->waiters_count_lock);
+ cv->waiters_count --;
+ last_waiter = (result == WAIT_OBJECT_0 + MINGW32_COND_BROADCAST) &&
+ (cv->waiters_count == 0);
+ LeaveCriticalSection(&cv->waiters_count_lock);
+
+ // Some thread called broadcast
+ if (last_waiter) {
+ // We're the last waiter to be notified or to stop waiting, so
+ // reset the manual event
+ ResetEvent(cv->events[MINGW32_COND_BROADCAST]);
+ }
+
+ // Reacquire the mutex
+ EnterCriticalSection((CRITICAL_SECTION *) mutex.mutex);
+ }
+
+ void ConditionSys::broadcast()
+ {
+ Mingw32Cond *cv = (Mingw32Cond *) cond;
+ int have_waiters;
+
+ // Avoid race conditions
+ EnterCriticalSection(&cv->waiters_count_lock);
+ have_waiters = cv->waiters_count > 0;
+ LeaveCriticalSection(&cv->waiters_count_lock);
+
+ if (have_waiters)
+ SetEvent(cv->events[MINGW32_COND_BROADCAST]);
+ }
+} /* namespace pf */
+#else
+
+namespace pf
+{
+ /*! system condition using windows API */
+ ConditionSys::ConditionSys () { cond = PF_NEW(CONDITION_VARIABLE); InitializeConditionVariable((CONDITION_VARIABLE*)cond); }
+ ConditionSys::~ConditionSys() { PF_DELETE((CONDITION_VARIABLE*)cond); }
+ void ConditionSys::wait(MutexSys& mutex) { SleepConditionVariableCS((CONDITION_VARIABLE*)cond, (CRITICAL_SECTION*)mutex.mutex, INFINITE); }
+ void ConditionSys::broadcast() { WakeAllConditionVariable((CONDITION_VARIABLE*)cond); }
+} /* namespace pf */
+#endif /* __GNUC__ */
+#endif /* __WIN32__ */
+
+#if defined(__UNIX__)
+#include <pthread.h>
+namespace pf
+{
+ ConditionSys::ConditionSys () { cond = PF_NEW(pthread_cond_t); pthread_cond_init((pthread_cond_t*)cond,NULL); }
+ ConditionSys::~ConditionSys() { PF_DELETE((pthread_cond_t*)cond); }
+ void ConditionSys::wait(MutexSys& mutex) { pthread_cond_wait((pthread_cond_t*)cond, (pthread_mutex_t*)mutex.mutex); }
+ void ConditionSys::broadcast() { pthread_cond_broadcast((pthread_cond_t*)cond); }
+} /* namespace pf */
+#endif /* __UNIX__ */
+
diff --git a/backend/src/sys/condition.hpp b/backend/src/sys/condition.hpp
new file mode 100644
index 00000000..a6d71f72
--- /dev/null
+++ b/backend/src/sys/condition.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_CONDITION_HPP__
+#define __PF_CONDITION_HPP__
+
+#include "sys/mutex.hpp"
+
+namespace pf
+{
+ class ConditionSys
+ {
+ public:
+ ConditionSys(void);
+ ~ConditionSys(void);
+ void wait(class MutexSys& mutex);
+ void broadcast(void);
+ protected:
+ void* cond;
+ };
+}
+
+#endif
+
diff --git a/backend/src/sys/constants.hpp b/backend/src/sys/constants.hpp
new file mode 100644
index 00000000..9849d11d
--- /dev/null
+++ b/backend/src/sys/constants.hpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_CONSTANTS_HPP__
+#define __PF_CONSTANTS_HPP__
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#include <limits>
+
+namespace pf
+{
+ static struct NullTy {
+ } null MAYBE_UNUSED;
+
+ static struct TrueTy {
+ INLINE operator bool( ) const { return true; }
+ } True MAYBE_UNUSED;
+
+ static struct FalseTy {
+ INLINE operator bool( ) const { return false; }
+ } False MAYBE_UNUSED;
+
+ static struct ZeroTy
+ {
+ INLINE operator double( ) const { return 0; }
+ INLINE operator float ( ) const { return 0; }
+ INLINE operator int64 ( ) const { return 0; }
+ INLINE operator uint64( ) const { return 0; }
+ INLINE operator int32 ( ) const { return 0; }
+ INLINE operator uint32( ) const { return 0; }
+ INLINE operator int16 ( ) const { return 0; }
+ INLINE operator uint16( ) const { return 0; }
+ INLINE operator int8 ( ) const { return 0; }
+ INLINE operator uint8 ( ) const { return 0; }
+#ifndef __MSVC__
+ INLINE operator size_t( ) const { return 0; }
+#endif
+
+ } zero MAYBE_UNUSED;
+
+ static struct OneTy
+ {
+ INLINE operator double( ) const { return 1; }
+ INLINE operator float ( ) const { return 1; }
+ INLINE operator int64 ( ) const { return 1; }
+ INLINE operator uint64( ) const { return 1; }
+ INLINE operator int32 ( ) const { return 1; }
+ INLINE operator uint32( ) const { return 1; }
+ INLINE operator int16 ( ) const { return 1; }
+ INLINE operator uint16( ) const { return 1; }
+ INLINE operator int8 ( ) const { return 1; }
+ INLINE operator uint8 ( ) const { return 1; }
+#ifndef __MSVC__
+ INLINE operator size_t( ) const { return 1; }
+#endif
+ } one MAYBE_UNUSED;
+
+ static struct NegInfTy
+ {
+ INLINE operator double( ) const { return -std::numeric_limits<double>::infinity(); }
+ INLINE operator float ( ) const { return -std::numeric_limits<float>::infinity(); }
+ INLINE operator int64 ( ) const { return std::numeric_limits<int64>::min(); }
+ INLINE operator uint64( ) const { return std::numeric_limits<uint64>::min(); }
+ INLINE operator int32 ( ) const { return std::numeric_limits<int32>::min(); }
+ INLINE operator uint32( ) const { return std::numeric_limits<uint32>::min(); }
+ INLINE operator int16 ( ) const { return std::numeric_limits<int16>::min(); }
+ INLINE operator uint16( ) const { return std::numeric_limits<uint16>::min(); }
+ INLINE operator int8 ( ) const { return std::numeric_limits<int8>::min(); }
+ INLINE operator uint8 ( ) const { return std::numeric_limits<uint8>::min(); }
+#ifndef __MSVC__
+ INLINE operator size_t( ) const { return std::numeric_limits<size_t>::min(); }
+#endif
+
+ } neg_inf MAYBE_UNUSED;
+
+ static struct PosInfTy
+ {
+ INLINE operator double( ) const { return std::numeric_limits<double>::infinity(); }
+ INLINE operator float ( ) const { return std::numeric_limits<float>::infinity(); }
+ INLINE operator int64 ( ) const { return std::numeric_limits<int64>::max(); }
+ INLINE operator uint64( ) const { return std::numeric_limits<uint64>::max(); }
+ INLINE operator int32 ( ) const { return std::numeric_limits<int32>::max(); }
+ INLINE operator uint32( ) const { return std::numeric_limits<uint32>::max(); }
+ INLINE operator int16 ( ) const { return std::numeric_limits<int16>::max(); }
+ INLINE operator uint16( ) const { return std::numeric_limits<uint16>::max(); }
+ INLINE operator int8 ( ) const { return std::numeric_limits<int8>::max(); }
+ INLINE operator uint8 ( ) const { return std::numeric_limits<uint8>::max(); }
+#ifndef _WIN32
+ INLINE operator size_t( ) const { return std::numeric_limits<size_t>::max(); }
+#endif
+ } inf MAYBE_UNUSED, pos_inf MAYBE_UNUSED;
+
+ static struct NaNTy
+ {
+ INLINE operator double( ) const { return std::numeric_limits<double>::quiet_NaN(); }
+ INLINE operator float ( ) const { return std::numeric_limits<float>::quiet_NaN(); }
+ } nan MAYBE_UNUSED;
+
+ static struct UlpTy
+ {
+ INLINE operator double( ) const { return std::numeric_limits<double>::epsilon(); }
+ INLINE operator float ( ) const { return std::numeric_limits<float>::epsilon(); }
+ } ulp MAYBE_UNUSED;
+
+ static struct PiTy
+ {
+ INLINE operator double( ) const { return 3.14159265358979323846; }
+ INLINE operator float ( ) const { return 3.14159265358979323846f; }
+ } pi MAYBE_UNUSED;
+
+ static struct StepTy {
+ } step MAYBE_UNUSED;
+
+ static struct EmptyTy {
+ } empty MAYBE_UNUSED;
+
+ static struct FullTy {
+ } full MAYBE_UNUSED;
+
+ static const size_t KB = 1024u;
+ static const size_t MB = KB*KB;
+ static const size_t GB = KB*MB;
+}
+
+#endif
diff --git a/backend/src/sys/default_path.cpp b/backend/src/sys/default_path.cpp
new file mode 100644
index 00000000..3661feed
--- /dev/null
+++ b/backend/src/sys/default_path.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "sys/default_path.hpp"
+#include "platform.hpp"
+
+namespace pf
+{
+ const char *defaultPath[] = {
+ "./share/",
+ "../share/",
+ "../../share/",
+ "./",
+ "../",
+ "../../",
+ "./data/",
+ "../data/",
+ "../../data/"
+ };
+ const size_t defaultPathNum = ARRAY_ELEM_NUM(defaultPath);
+} /* namespace pf */
+
diff --git a/backend/src/sys/default_path.hpp b/backend/src/sys/default_path.hpp
new file mode 100644
index 00000000..5f841790
--- /dev/null
+++ b/backend/src/sys/default_path.hpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __DEFAULT_PATH_HPP__
+#define __DEFAULT_PATH_HPP__
+
+#include <cstdlib>
+
+namespace pf
+{
+ /*! Where you may find data files and shaders */
+ extern const char *defaultPath[];
+ /*! Number of default paths */
+ extern const size_t defaultPathNum;
+} /* namespace pf */
+
+#endif /* __DEFAULT_PATH_HPP__ */
+
diff --git a/backend/src/sys/filename.cpp b/backend/src/sys/filename.cpp
new file mode 100644
index 00000000..58221f5c
--- /dev/null
+++ b/backend/src/sys/filename.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "sys/platform.hpp"
+#include "sys/filename.hpp"
+
+namespace pf
+{
+#ifdef __WIN32__
+ const char path_sep = '\\';
+#else
+ const char path_sep = '/';
+#endif
+
+ /*! little helper to not depend on math */
+ static size_t maxInt(size_t a, size_t b) { return index_t(a) < index_t(b) ? b : a; }
+
+ /*! create an empty filename */
+ FileName::FileName () {}
+
+ /*! create a valid filename from a string */
+ FileName::FileName (const char* in) {
+ filename = in;
+ for (size_t i=0; i<filename.size(); i++)
+ if (filename[i] == '\\' || filename[i] == '/')
+ filename[i] = path_sep;
+ while (!filename.empty() && filename[filename.size()-1] == path_sep)
+ filename.resize(filename.size()-1);
+ }
+
+ /*! create a valid filename from a string */
+ FileName::FileName (const std::string& in) {
+ filename = in;
+ for (size_t i=0; i<filename.size(); i++)
+ if (filename[i] == '\\' || filename[i] == '/')
+ filename[i] = path_sep;
+ while (!filename.empty() && filename[filename.size()-1] == path_sep)
+ filename.resize(filename.size()-1);
+ }
+
+ /*! returns the path */
+ FileName FileName::path() const {
+ size_t pos = maxInt(filename.find_last_of('\\'),filename.find_last_of('/'));
+ if (pos == std::string::npos) return FileName();
+ return filename.substr(0,pos);
+ }
+
+ /*! returns the basename */
+ std::string FileName::base() const {
+ size_t pos = maxInt(filename.find_last_of('\\'),filename.find_last_of('/'));
+ if (pos == std::string::npos) return filename;
+ return filename.substr(pos+1);
+ }
+
+ /*! returns the extension */
+ std::string FileName::ext() const {
+ size_t pos = filename.find_last_of('.');
+ if (pos == std::string::npos) return "";
+ return filename.substr(pos+1);
+ }
+
+ /*! returns the basename without extension */
+ std::string FileName::name() const {
+ size_t start = maxInt(filename.find_last_of('\\'),filename.find_last_of('/')) + 1;
+ if (start == std::string::npos) start = 0;
+ size_t end = filename.find_last_of('.');
+ if (end == std::string::npos || end < start) end = filename.size();
+ return filename.substr(start, end - start);
+ }
+
+ /*! replaces the extension */
+ FileName FileName::setExt(const std::string& ext) const {
+ size_t start = maxInt(filename.find_last_of('\\'),filename.find_last_of('/')) + 1;
+ if (start == std::string::npos) start = 0;
+ size_t end = filename.find_last_of('.');
+ if (end == std::string::npos || end < start) return FileName(filename+ext);
+ return FileName(filename.substr(0,end)+ext);
+ }
+
+ /*! adds the extension */
+ FileName FileName::addExt(const std::string& ext) const {
+ return FileName(filename+ext);
+ }
+
+ /*! concatenates two filenames to this/other */
+ FileName FileName::operator +( const FileName& other ) const {
+ if (filename == "") return FileName(other);
+ else return FileName(filename + path_sep + other.filename);
+ }
+
+ /*! concatenates two filenames to this/other */
+ FileName FileName::operator +( const std::string& other ) const {
+ return operator+(FileName(other));
+ }
+
+ /*! removes the base from a filename (if possible) */
+ FileName FileName::operator -( const FileName& base ) const {
+ size_t pos = filename.find_first_of(base);
+ if (pos == std::string::npos) return *this;
+ return FileName(filename.substr(pos+1));
+ }
+
+ /*! output operator */
+ std::ostream& operator<<(std::ostream& cout, const FileName& filename) {
+ return cout << filename.filename;
+ }
+}
diff --git a/backend/src/sys/filename.hpp b/backend/src/sys/filename.hpp
new file mode 100644
index 00000000..4f4fb391
--- /dev/null
+++ b/backend/src/sys/filename.hpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_FILENAME_HPP__
+#define __PF_FILENAME_HPP__
+
+#include "platform.hpp"
+#include <string>
+#include <cstdio>
+
+namespace pf
+{
+ /*! Convenience class for handling file names and paths. */
+ class FileName
+ {
+ public:
+ /*! create an empty filename */
+ FileName ();
+ /*! create a valid filename from a string */
+ FileName (const char* filename);
+ /*! create a valid filename from a string */
+ FileName (const std::string& filename);
+ /*! auto convert into a string */
+ operator std::string() const { return filename; }
+ /*! returns a string of the filename */
+ const std::string str() const { return filename; }
+ /*! returns a c-string of the filename */
+ const char* c_str() const { return filename.c_str(); }
+ /*! returns the path of a filename */
+ FileName path() const;
+ /*! returns the file of a filename */
+ std::string base() const;
+ /*! returns the base of a filename without extension */
+ std::string name() const;
+ /*! returns the file extension */
+ std::string ext() const;
+ /*! replaces the file extension */
+ FileName setExt(const std::string& ext = "") const;
+ /*! adds file extension */
+ FileName addExt(const std::string& ext = "") const;
+ /*! concatenates two filenames to this/other */
+ FileName operator +( const FileName& other ) const;
+ /*! concatenates two filenames to this/other */
+ FileName operator +( const std::string& other ) const;
+ /*! removes the base from a filename (if possible) */
+ FileName operator -( const FileName& base ) const;
+ /*! output operator */
+ friend std::ostream& operator<<(std::ostream& cout, const FileName& filename);
+ private:
+ std::string filename;
+ PF_CLASS(FileName);
+ };
+}
+
+#endif /* __PF_FILENAME_HPP__ */
+
diff --git a/backend/src/sys/fixed_array.hpp b/backend/src/sys/fixed_array.hpp
new file mode 100644
index 00000000..68593ecf
--- /dev/null
+++ b/backend/src/sys/fixed_array.hpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_FIXED_ARRAY_HPP__
+#define __PF_FIXED_ARRAY_HPP__
+
+#include "platform.hpp"
+#include <cstring>
+
+namespace pf
+{
+ /*! Regular C array but with bound checks */
+ template<typename T, size_t N>
+ class fixed_array
+ {
+ public:
+ /*! Do not initialize the data */
+ fixed_array(void) {}
+ /*! Copy the input array */
+ fixed_array(const T array[N]) { std::memcpy(elem, array, N * sizeof(T)); }
+ /*! First element (non const) */
+ T* begin(void) { return &elem[0]; }
+ /*! First non-valid element (non const) */
+ T* end(void) { return begin() + N; }
+ /*! First element (const) */
+ const T* begin(void) const { return &elem[0]; }
+ /*! First non-valid element (const) */
+ const T* end(void) const { return begin() + N; }
+ /*! Number of elements in the array */
+ size_t size(void) const { return N; }
+ /*! Get the pointer to the data (non-const) */
+ T* data(void) { return &elem[0]; }
+ /*! Get the pointer to the data (const) */
+ const T* data(void) const { return &elem[0]; }
+ /*! First element (const) */
+ const T& front(void) const { return *begin(); }
+ /*! Last element (const) */
+ const T& back(void) const { return *(end() - 1); }
+ /*! First element (non-const) */
+ T& front(void) { return *begin(); }
+ /*! Last element (non-const) */
+ T& back(void) { return *(end() - 1); }
+ /*! Get element at position index (with bound check) */
+ INLINE T& operator[] (size_t index) {
+ PF_ASSERT(index < size());
+ return elem[index];
+ }
+ /*! Get element at position index (with bound check) */
+ INLINE const T& operator[] (size_t index) const {
+ PF_ASSERT(index < size());
+ return elem[index];
+ }
+ private:
+ T elem[N]; //!< Store the elements
+ STATIC_ASSERT(N > 0); //!< zero element is not allowed
+ PF_CLASS(fixed_array);
+ };
+
+} /* namespace pf */
+
+#endif /* __PF_FIXED_ARRAY_HPP__ */
+
+
diff --git a/backend/src/sys/hash_map.hpp b/backend/src/sys/hash_map.hpp
new file mode 100644
index 00000000..ab1a317d
--- /dev/null
+++ b/backend/src/sys/hash_map.hpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_HASH_MAP_HPP__
+#define __PF_HASH_MAP_HPP__
+
+#include "sys/platform.hpp"
+
+#ifdef __MSVC__
+#include <unordered_map>
+#else
+#include <tr1/unordered_map>
+#endif /* __MSVC__ */
+
+namespace pf
+{
+ /*! Add specific allocator to the hash map */
+ template <class Key,
+ class T,
+ class Hash = std::hash<Key>,
+ class Pred = std::equal_to<Key>>
+ class hash_map : public std::tr1::unordered_map<Key,T,Hash,Pred,Allocator<std::pair<const Key,T>>>
+ {
+ public:
+ // Typedefs
+ typedef std::pair<const Key, T> value_type;
+ typedef Allocator<value_type> allocator_type;
+ typedef std::tr1::unordered_map<Key,T,Hash,Pred,allocator_type> parent_type;
+ typedef typename allocator_type::size_type size_type;
+ typedef Key key_type;
+ typedef T mapped_type;
+ typedef Hash hasher;
+ typedef Pred key_equal;
+
+ /*! Default constructor */
+ INLINE explicit hash_map(size_type n = 3,
+ const hasher& hf = hasher(),
+ const key_equal& eql = key_equal(),
+ const allocator_type& a = allocator_type()) :
+ parent_type(n, hf, eql, a) {}
+ /*! Iteration constructor */
+ template <class InputIterator>
+ INLINE hash_map(InputIterator first,
+ InputIterator last,
+ size_type n = 3,
+ const hasher& hf = hasher(),
+ const key_equal& eql = key_equal(),
+ const allocator_type& a = allocator_type()) :
+ parent_type(first,last,n,hf,eql,a) {}
+ /*! Copy constructor */
+ INLINE hash_map(const hash_map &other) : parent_type(other) {}
+ PF_CLASS(hash_map);
+ };
+} /* namespace pf */
+
+#endif /* __PF_HASH_MAP_HPP__ */
+
diff --git a/backend/src/sys/intrinsics.hpp b/backend/src/sys/intrinsics.hpp
new file mode 100644
index 00000000..99f55527
--- /dev/null
+++ b/backend/src/sys/intrinsics.hpp
@@ -0,0 +1,210 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_INTRINSICS_H__
+#define __PF_INTRINSICS_H__
+
+#include "sys/platform.hpp"
+#include <xmmintrin.h>
+#include <emmintrin.h>
+
+#if defined(__MSVC__)
+
+#include <intrin.h>
+
+#define PF_COMPILER_WRITE_BARRIER _WriteBarrier()
+#define PF_COMPILER_READ_WRITE_BARRIER _ReadWriteBarrier()
+
+#if _MSC_VER >= 1400
+#pragma intrinsic(_ReadBarrier)
+#define PF_COMPILER_READ_BARRIER _ReadBarrier()
+#else
+#define PF_COMPILER_READ_BARRIER _ReadWriteBarrier()
+#endif /* _MSC_VER >= 1400 */
+
+INLINE int __bsf(int v) {
+ unsigned long r = 0; _BitScanForward(&r,v); return r;
+}
+
+INLINE int __bsr(int v) {
+ unsigned long r = 0; _BitScanReverse(&r,v); return r;
+}
+
+INLINE int __btc(int v, int i) {
+ long r = v; _bittestandcomplement(&r,i); return r;
+}
+
+INLINE int __bts(int v, int i) {
+ long r = v; _bittestandset(&r,i); return r;
+}
+
+INLINE int __btr(int v, int i) {
+ long r = v; _bittestandreset(&r,i); return r;
+}
+
+INLINE void memoryFence(void) { _mm_mfence(); }
+
+#if defined(__X86_64__) && !defined(__INTEL_COMPILER)
+
+INLINE size_t __bsf(size_t v) {
+ unsigned long r = 0; _BitScanForward64(&r,v); return r;
+}
+
+INLINE size_t __bsr(size_t v) {
+ unsigned long r = 0; _BitScanReverse64(&r,v); return r;
+}
+
+INLINE size_t __btc(size_t v, size_t i) {
+ __int64 r = v; _bittestandcomplement64(&r,i); return r;
+}
+
+INLINE size_t __bts(size_t v, size_t i) {
+ __int64 r = v; _bittestandset64(&r,i); return r;
+}
+
+INLINE size_t __btr(size_t v, size_t i) {
+ __int64 r = v; _bittestandreset64(&r,i); return r;
+}
+
+#endif /* defined(__X86_64__) && !defined(__INTEL_COMPILER) */
+
+typedef int32 atomic32_t;
+
+INLINE int32 atomic_add(volatile int32* m, const int32 v) {
+ return _InterlockedExchangeAdd((volatile long*)m,v);
+}
+
+INLINE int32 atomic_cmpxchg(volatile int32* m, const int32 v, const int32 c) {
+ return _InterlockedCompareExchange((volatile long*)m,v,c);
+}
+
+#if defined(__X86_64__)
+
+typedef int64 atomic_t;
+
+INLINE int64 atomic_add(volatile int64* m, const int64 v) {
+ return _InterlockedExchangeAdd64(m,v);
+}
+
+INLINE int64 atomic_cmpxchg(volatile int64* m, const int64 v, const int64 c) {
+ return _InterlockedCompareExchange64(m,v,c);
+}
+
+#else
+
+typedef int32 atomic_t;
+
+#endif /* defined(__X86_64__) */
+
+#else
+
+INLINE unsigned int __popcnt(unsigned int in) {
+ int r = 0; asm ("popcnt %1,%0" : "=r"(r) : "r"(in)); return r;
+}
+
+INLINE int __bsf(int v) {
+ int r = 0; asm ("bsf %1,%0" : "=r"(r) : "r"(v)); return r;
+}
+
+INLINE int __bsr(int v) {
+ int r = 0; asm ("bsr %1,%0" : "=r"(r) : "r"(v)); return r;
+}
+
+INLINE int __btc(int v, int i) {
+ int r = 0; asm ("btc %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
+}
+
+INLINE int __bts(int v, int i) {
+ int r = 0; asm ("bts %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
+}
+
+INLINE int __btr(int v, int i) {
+ int r = 0; asm ("btr %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
+}
+
+INLINE size_t __bsf(size_t v) {
+ size_t r = 0; asm ("bsf %1,%0" : "=r"(r) : "r"(v)); return r;
+}
+
+INLINE size_t __bsr(size_t v) {
+ size_t r = 0; asm ("bsr %1,%0" : "=r"(r) : "r"(v)); return r;
+}
+
+INLINE size_t __btc(size_t v, size_t i) {
+ size_t r = 0; asm ("btc %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
+}
+
+INLINE size_t __bts(size_t v, size_t i) {
+ size_t r = 0; asm ("bts %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
+}
+
+INLINE size_t __btr(size_t v, size_t i) {
+ size_t r = 0; asm ("btr %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
+}
+
+INLINE void memoryFence(void) { _mm_mfence(); }
+
+typedef int32 atomic32_t;
+
+INLINE int32 atomic_add(int32 volatile* value, int32 input)
+{ asm volatile("lock xadd %0,%1" : "+r" (input), "+m" (*value) : "r" (input), "m" (*value)); return input; }
+
+INLINE int32 atomic_cmpxchg(int32 volatile* value, const int32 input, int32 comparand)
+{ asm volatile("lock cmpxchg %2,%0" : "=m" (*value), "=a" (comparand) : "r" (input), "m" (*value), "a" (comparand) : "flags"); return comparand; }
+
+#if defined(__X86_64__)
+
+ typedef int64 atomic_t;
+
+ INLINE int64 atomic_add(int64 volatile* value, int64 input)
+ { asm volatile("lock xaddq %0,%1" : "+r" (input), "+m" (*value) : "r" (input), "m" (*value)); return input; }
+
+ INLINE int64 atomic_cmpxchg(int64 volatile* value, const int64 input, int64 comparand)
+ { asm volatile("lock cmpxchgq %2,%0" : "+m" (*value), "+a" (comparand) : "r" (input), "m" (*value), "r" (comparand) : "flags"); return comparand; }
+
+#else
+
+ typedef int32 atomic_t;
+
+#endif /* defined(__X86_64__) */
+
+#define PF_COMPILER_READ_WRITE_BARRIER asm volatile("" ::: "memory");
+#define PF_COMPILER_WRITE_BARRIER PF_COMPILER_READ_WRITE_BARRIER
+#define PF_COMPILER_READ_BARRIER PF_COMPILER_READ_WRITE_BARRIER
+
+#endif /* __MSVC__ */
+
+template <typename T>
+INLINE T __load_acquire(volatile T *ptr)
+{
+ PF_COMPILER_READ_WRITE_BARRIER;
+ T x = *ptr; // for x86, load == load_acquire
+ PF_COMPILER_READ_WRITE_BARRIER;
+ return x;
+}
+
+template <typename T>
+INLINE void __store_release(volatile T *ptr, T x)
+{
+ PF_COMPILER_READ_WRITE_BARRIER;
+ *ptr = x; // for x86, store == store_release
+ PF_COMPILER_READ_WRITE_BARRIER;
+}
+#endif /* __PF_INTRINSICS_H__ */
+
diff --git a/backend/src/sys/library.cpp b/backend/src/sys/library.cpp
new file mode 100644
index 00000000..815bd592
--- /dev/null
+++ b/backend/src/sys/library.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "sys/library.hpp"
+#include "sys/sysinfo.hpp"
+#include "sys/filename.hpp"
+
+////////////////////////////////////////////////////////////////////////////////
+/// Windows Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__WIN32__)
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+namespace pf
+{
+ /* opens a shared library */
+ lib_t openLibrary(const std::string& file)
+ {
+ std::string fullName = file+".dll";
+ HMODULE handle = LoadLibraryA(fullName.c_str());
+ if (handle) return lib_t(handle);
+ handle = LoadLibrary((getExecutableFileName() + fullName).c_str());
+ return lib_t(handle);
+ }
+
+ /* returns address of a symbol from the library */
+ void* getSymbol(lib_t lib, const std::string& sym) {
+ return (void*) GetProcAddress(HMODULE(lib),sym.c_str());
+ }
+
+ /* closes the shared library */
+ void closeLibrary(lib_t lib) {
+ FreeLibrary(HMODULE(lib));
+ }
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// Unix Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__UNIX__)
+
+#include <dlfcn.h>
+
+namespace pf
+{
+ /* opens a shared library */
+ lib_t openLibrary(const std::string& file)
+ {
+#if defined(__MACOSX__)
+ std::string fullName = "lib"+file+".dylib";
+#else
+ std::string fullName = "lib"+file+".so";
+#endif
+ void* lib = dlopen(fullName.c_str(),RTLD_NOW);
+ if (lib) return lib_t(lib);
+ lib = dlopen((getExecutableFileName() + fullName).c_str(),RTLD_NOW);
+ return lib_t(lib);
+ }
+
+ /* returns address of a symbol from the library */
+ void* getSymbol(lib_t lib, const std::string& sym) {
+ return dlsym(lib,sym.c_str());
+ }
+
+ /* closes the shared library */
+ void closeLibrary(lib_t lib) {
+ dlclose(lib);
+ }
+}
+#endif
diff --git a/backend/src/sys/library.hpp b/backend/src/sys/library.hpp
new file mode 100644
index 00000000..8dcb1a93
--- /dev/null
+++ b/backend/src/sys/library.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_LIBRARY_HPP__
+#define __PF_LIBRARY_HPP__
+
+#include <string>
+
+#include "sys/platform.hpp"
+
+namespace pf
+{
+ /*! type for shared library */
+ typedef struct opaque_lib_t* lib_t;
+ /*! loads a shared library */
+ lib_t openLibrary(const std::string& file);
+ /*! returns address of a symbol from the library */
+ void* getSymbol(lib_t lib, const std::string& sym);
+ /*! unloads a shared library */
+ void closeLibrary(lib_t lib);
+} /* namespace pf */
+
+#endif /* __PF_LIBRARY_HPP__ */
+
diff --git a/backend/src/sys/list.hpp b/backend/src/sys/list.hpp
new file mode 100644
index 00000000..6f479d28
--- /dev/null
+++ b/backend/src/sys/list.hpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_LIST_HPP__
+#define __PF_LIST_HPP__
+
+#include "sys/platform.hpp"
+#include <list>
+
+namespace pf
+{
+ /*! Use custom allocator instead of std one */
+ template <typename T>
+ class list : public std::list<T, Allocator<T>>
+ {
+ public:
+ // Typedefs
+ typedef T value_type;
+ typedef Allocator<value_type> allocator_type;
+ typedef std::list<T, allocator_type> parent_type;
+ typedef typename allocator_type::size_type size_type;
+
+ /*! Default constructor */
+ INLINE explicit list(const allocator_type &a = allocator_type()) :
+ parent_type(a) {}
+ /*! Repetitive constructor */
+ INLINE explicit list(size_type n,
+ const T &value = T(),
+ const allocator_type &a = allocator_type()) :
+ parent_type(n, value, a) {}
+ /*! Iteration constructor */
+ template <class InputIterator>
+ INLINE list(InputIterator first,
+ InputIterator last,
+ const allocator_type &a = allocator_type()) :
+ parent_type(first, last, a) {}
+ /*! Copy constructor */
+ INLINE list(const list &x) : parent_type(x) {}
+ PF_CLASS(list);
+ };
+} /* namespace pf */
+
+#endif /* __PF_LIST_HPP__ */
+
diff --git a/backend/src/sys/logging.cpp b/backend/src/sys/logging.cpp
new file mode 100644
index 00000000..6f4c8401
--- /dev/null
+++ b/backend/src/sys/logging.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "sys/logging.hpp"
+#include "sys/filename.hpp"
+
+namespace pf
+{
+ LoggerStream::LoggerStream(void) : next(NULL) {}
+ LoggerStream::~LoggerStream(void) {}
+
+ LoggerBuffer::LoggerBuffer(void) : logger(NULL) {}
+
+ LoggerBuffer& LoggerBuffer::operator<< (LoggerFlushTy) {
+ logger->output(ss.str());
+ ss.str("");
+ return *this;
+ }
+
+ LoggerBuffer& LoggerBuffer::operator<< (const LoggerInfo &info) {
+ FileName fileName(info.file);
+ return *this << fileName.base() << " at " << info.function << " line " << info.line;
+ }
+
+ Logger::Logger(void) : streams(NULL) {
+ const uint32 threadNum = 1;
+ this->buffers = PF_NEW_ARRAY(LoggerBuffer, threadNum);
+ for (uint32 i = 0; i < threadNum; ++i) this->buffers[i].logger = this;
+ this->startTime = getSeconds();
+ }
+
+ Logger::~Logger(void) {
+ FATAL_IF(streams != NULL, "Remove all streams before deleting the logger");
+ PF_DELETE_ARRAY(buffers);
+ }
+
+ void Logger::output(const std::string &str) {
+ Lock<MutexSys> lock(mutex);
+ LoggerStream *stream = this->streams;
+ while (stream) {
+ *stream << str;
+ stream = stream->next;
+ }
+ }
+
+ void Logger::insert(LoggerStream &stream) {
+ Lock<MutexSys> lock(mutex);
+ stream.next = this->streams;
+ this->streams = &stream;
+ }
+
+ void Logger::remove(LoggerStream &stream) {
+ Lock<MutexSys> lock(mutex);
+ LoggerStream *curr = this->streams;
+ LoggerStream *pred = NULL;
+ while (curr) {
+ if (curr == &stream)
+ break;
+ pred = curr;
+ curr = curr->next;
+ }
+ FATAL_IF (curr == NULL, "Unable to find the given stream");
+ if (pred)
+ pred->next = curr->next;
+ else
+ this->streams = curr->next;
+ }
+
+ Logger *logger = NULL;
+} /* namespace pf */
+
diff --git a/backend/src/sys/logging.hpp b/backend/src/sys/logging.hpp
new file mode 100644
index 00000000..ae69e321
--- /dev/null
+++ b/backend/src/sys/logging.hpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_LOGGING_HPP__
+#define __PF_LOGGING_HPP__
+
+#include "sys/mutex.hpp"
+#include "sys/platform.hpp"
+#include <sstream>
+#include <iomanip>
+
+namespace pf
+{
+ class Logger;
+ class LoggerBuffer;
+ class LoggerStream;
+
+ /*! A logger stream is one way to output a string. It can be a file,
+ * stdout, the in-game console and so on...
+ */
+ class LoggerStream
+ {
+ public:
+ LoggerStream(void);
+ virtual ~LoggerStream(void);
+ virtual LoggerStream& operator<< (const std::string &str) = 0;
+ private:
+ friend class Logger;
+ LoggerStream *next; //!< We chain the logger elements together
+ };
+
+ /*! Helper and proxy structures to display various information */
+ static struct LoggerFlushTy { } loggerFlush MAYBE_UNUSED;
+ struct LoggerInfo {
+ INLINE LoggerInfo(const char *file, const char *function, int line) :
+ file(file), function(function), line(line) {}
+ const char *file, *function;
+ int line;
+ PF_CLASS(LoggerInfo);
+ };
+
+ /*! Used to lazily create strings from the user defined logs. When destroyed
+ * or flushed, it displays everything in one piece
+ */
+ class LoggerBuffer
+ {
+ public:
+ template <typename T> LoggerBuffer& operator<< (const T &x) {
+ ss << x;
+ return *this;
+ }
+ LoggerBuffer& operator<< (LoggerFlushTy);
+ LoggerBuffer& operator<< (const LoggerInfo&);
+ /*! Output the info a nice format */
+ LoggerBuffer& info(const char *file, const char *function, int line);
+ private:
+ friend class Logger;
+ LoggerBuffer(void);
+ Logger *logger; //!< The logger that created this buffer
+ std::stringstream ss; //!< Stores all the user strings
+ PF_CLASS(LoggerBuffer);
+ };
+
+ /*! Central class to log anything from the engine */
+ class Logger
+ {
+ public:
+ Logger(void);
+ ~Logger(void);
+ /*! Output the string into all the attached streams */
+ void output(const std::string &str);
+ template <typename T> LoggerBuffer& operator<< (const T &x) {
+ const uint32 bufferID = 0;
+ LoggerBuffer &buffer = buffers[bufferID];
+ buffer << "[" << "thread " << std::setw(2) << bufferID << "] ";
+ buffer << "[" << std::setw(12) << std::fixed << getSeconds() - startTime << "s] " << x;
+ return buffer;
+ }
+ void insert(LoggerStream &stream);
+ void remove(LoggerStream &stream);
+ private:
+ MutexSys mutex; //!< To insert / remove streams and output strings
+ LoggerStream *streams; //!< All the output streams
+ LoggerBuffer *buffers; //!< One buffer per thread
+ double startTime; //!< When the logger has been created
+ PF_CLASS(Logger);
+ };
+
+ /*! We have one logger for the application */
+ extern Logger *logger;
+
+} /* namespace pf */
+
+/*! Macros to handle logging information in the code */
+#define PF_LOG_HERE LoggerInfo(__FILE__, __FUNCTION__, __LINE__)
+#define PF_INFO " ######## " << PF_LOG_HERE
+
+/*! Verbose macros: they add logging position and thread ID */
+#define PF_WARNING_V(MSG) do { \
+ if (logger) *logger << "WARNING " << MSG << PF_INFO << "\n" << loggerFlush; \
+} while (0)
+
+#define PF_ERROR_V(MSG) do { \
+ if (logger) *logger << "ERROR " << MSG << PF_INFO << "\n" << loggerFlush; \
+} while (0)
+
+#define PF_MSG_V(MSG) do { \
+ if (logger) *logger << MSG << PF_INFO << "\n" << loggerFlush; \
+} while (0)
+
+/*! Regular macros: just the user message */
+#define PF_WARNING(MSG) do { \
+ if (logger) *logger << "WARNING " << MSG << "\n" << loggerFlush; \
+} while (0)
+
+#define PF_ERROR(MSG) do { \
+ if (logger) *logger << "ERROR " << MSG << "\n" << loggerFlush; \
+} while (0)
+
+#define PF_MSG(MSG) do { \
+ if (logger) *logger << MSG << "\n" << loggerFlush; \
+} while (0)
+
+#endif /* __PF_LOGGING_HPP__ */
+
diff --git a/backend/src/sys/map.hpp b/backend/src/sys/map.hpp
new file mode 100644
index 00000000..c673b86f
--- /dev/null
+++ b/backend/src/sys/map.hpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_MAP_HPP__
+#define __PF_MAP_HPP__
+
+#include "sys/platform.hpp"
+#include <map>
+
+namespace pf
+{
+ /*! Use custom allocator instead of std one */
+ template<class Key, class T, class Pred = std::less<Key>>
+ class map : public std::map<Key,T,Pred,Allocator<std::pair<const Key, T>>>
+ {
+ public:
+ // Typedefs
+ typedef std::pair<const Key, T> value_type;
+ typedef Allocator<value_type> allocator_type;
+ typedef std::map<Key,T,Pred,allocator_type> parent_type;
+ typedef Key key_type;
+ typedef T mapped_type;
+ typedef Pred key_compare;
+ typedef typename allocator_type::pointer pointer;
+ typedef typename allocator_type::const_pointer const_pointer;
+ typedef typename allocator_type::reference reference;
+ typedef typename allocator_type::const_reference const_reference;
+
+ /*! Default constructor */
+ INLINE map(const key_compare &comp = key_compare(),
+ const allocator_type &a = allocator_type()) :
+ parent_type(comp, a) {}
+ /*! Iteration constructor */
+ template<class InputIterator>
+ INLINE map(InputIterator first,
+ InputIterator last,
+ const key_compare &comp = key_compare(),
+ const allocator_type& a = allocator_type()) :
+ parent_type(first, last, comp, a) {}
+ /*! Copy constructor */
+ INLINE map(const map& x) : parent_type(x) {}
+ PF_CLASS(map);
+ };
+} /* namespace pf */
+
+#endif /* __PF_MAP_HPP__ */
+
diff --git a/backend/src/sys/mutex.cpp b/backend/src/sys/mutex.cpp
new file mode 100644
index 00000000..590ad5d4
--- /dev/null
+++ b/backend/src/sys/mutex.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "sys/mutex.hpp"
+
+#if defined(__WIN32__)
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+namespace pf
+{
+ /*! system mutex using windows API */
+ MutexSys::MutexSys( void ) { mutex = new CRITICAL_SECTION; InitializeCriticalSection((CRITICAL_SECTION*)mutex); }
+ MutexSys::~MutexSys( void ) { DeleteCriticalSection((CRITICAL_SECTION*)mutex); delete ((CRITICAL_SECTION*)mutex); }
+ void MutexSys::lock( void ) { EnterCriticalSection((CRITICAL_SECTION*)mutex); }
+ void MutexSys::unlock( void ) { LeaveCriticalSection((CRITICAL_SECTION*)mutex); }
+}
+#endif
+
+#if defined(__UNIX__)
+#include <pthread.h>
+
+namespace pf
+{
+ /*! system mutex using pthreads */
+ MutexSys::MutexSys( void ) { mutex = new pthread_mutex_t; pthread_mutex_init((pthread_mutex_t*)mutex, NULL); }
+ MutexSys::~MutexSys( void ) { pthread_mutex_destroy((pthread_mutex_t*)mutex); delete ((pthread_mutex_t*)mutex); }
+ void MutexSys::lock( void ) { pthread_mutex_lock((pthread_mutex_t*)mutex); }
+ void MutexSys::unlock( void ) { pthread_mutex_unlock((pthread_mutex_t*)mutex); }
+}
+#endif
+
diff --git a/backend/src/sys/mutex.hpp b/backend/src/sys/mutex.hpp
new file mode 100644
index 00000000..b29b3c88
--- /dev/null
+++ b/backend/src/sys/mutex.hpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_MUTEX_H__
+#define __PF_MUTEX_H__
+
+#include "platform.hpp"
+#include "atomic.hpp"
+#include <xmmintrin.h>
+
+namespace pf
+{
+ class MutexSys {
+ friend class ConditionSys;
+ public:
+ MutexSys(void);
+ ~MutexSys(void);
+ void lock(void);
+ void unlock(void);
+ protected:
+ void* mutex;
+ MutexSys(const MutexSys&); // don't implement
+ MutexSys& operator= (const MutexSys&); // don't implement
+ PF_CLASS(MutexSys);
+ };
+
+ /*! active mutex */
+ class MutexActive {
+ public:
+ INLINE MutexActive(void) : $lock(LOCK_IS_FREE) {}
+ INLINE void lock(void) {
+ PF_COMPILER_READ_BARRIER;
+ while (cmpxchg($lock, LOCK_IS_TAKEN, LOCK_IS_FREE) != LOCK_IS_FREE)
+ _mm_pause();
+ PF_COMPILER_READ_BARRIER;
+ }
+ INLINE void unlock(void) { $lock.storeRelease(LOCK_IS_FREE); }
+ protected:
+ enum ${ LOCK_IS_FREE = 0, LOCK_IS_TAKEN = 1 };
+ Atomic $lock;
+ MutexActive(const MutexActive&); // don't implement
+ MutexActive& operator=(const MutexActive&); // don't implement
+ PF_CLASS(MutexActive);
+ };
+
+ /*! safe mutex lock and unlock helper */
+ template<typename Mutex> class Lock {
+ public:
+ Lock (Mutex& mutex) : mutex(mutex) { mutex.lock(); }
+ ~Lock() { mutex.unlock(); }
+ protected:
+ Mutex& mutex;
+ Lock(const Lock&); // don't implement
+ Lock& operator= (const Lock&); // don't implement
+ PF_CLASS(Lock);
+ };
+}
+
+#endif
diff --git a/backend/src/sys/platform.cpp b/backend/src/sys/platform.cpp
new file mode 100644
index 00000000..96fab95a
--- /dev/null
+++ b/backend/src/sys/platform.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "sys/platform.hpp"
+#include "sys/intrinsics.hpp"
+#include <string>
+
+////////////////////////////////////////////////////////////////////////////////
+/// Windows Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __WIN32__
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+namespace pf
+{
+ double getSeconds() {
+ LARGE_INTEGER freq, val;
+ QueryPerformanceFrequency(&freq);
+ QueryPerformanceCounter(&val);
+ return (double)val.QuadPart / (double)freq.QuadPart;
+ }
+
+ void FATAL(const std::string &msg) {
+ std::cerr << msg << std::endl;
+ MessageBox(NULL, msg.c_str(), "Fatal Error", MB_OK | MB_ICONEXCLAMATION);
+ PF_ASSERT(0);
+#ifdef __GNUC__
+ exit(-1);
+#else
+ _exit(-1);
+#endif /* __GNUC__ */
+ }
+
+} /* namespace pf */
+#endif /* __WIN32__ */
+
+////////////////////////////////////////////////////////////////////////////////
+/// Unix Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__UNIX__)
+
+#include <sys/time.h>
+
+namespace pf
+{
+ double getSeconds() {
+ struct timeval tp; gettimeofday(&tp,NULL);
+ return double(tp.tv_sec) + double(tp.tv_usec)/1E6;
+ }
+
+ void FATAL(const std::string &msg) {
+ std::cerr << msg << std::endl;
+ PF_ASSERT(0);
+ _exit(-1);
+ }
+} /* namespace pf */
+
+#endif /* __UNIX__ */
+
diff --git a/backend/src/sys/platform.hpp b/backend/src/sys/platform.hpp
new file mode 100644
index 00000000..ecd205fb
--- /dev/null
+++ b/backend/src/sys/platform.hpp
@@ -0,0 +1,373 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_PLATFORM_HPP__
+#define __PF_PLATFORM_HPP__
+#include <cstddef>
+#include <cstdlib>
+#include <cstdio>
+#include <iostream>
+#include <cassert>
+
+////////////////////////////////////////////////////////////////////////////////
+/// CPU architecture
+////////////////////////////////////////////////////////////////////////////////
+
+/* detect 32 or 64 platform */
+#if defined(__x86_64__) || defined(__ia64__) || defined(_M_X64)
+#define __X86_64__
+#else
+#define __X86__
+#endif
+
+/* We require SSE ... */
+#ifndef __SSE__
+#define __SSE__
+#endif
+
+/* ... and SSE2 */
+#ifndef __SSE2__
+#define __SSE2__
+#endif
+
+#if defined(_INCLUDED_IMM)
+// #define __AVX__
+#endif
+
+#if defined(_MSC_VER) && (_MSC_VER < 1600) && !defined(__INTEL_COMPILER) || defined(_DEBUG) && defined(_WIN32)
+#define __NO_AVX__
+#endif
+
+#if defined(_MSC_VER) && !defined(__SSE4_2__)
+// #define __SSE4_2__ //! activates SSE4.2 support
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// Operating system
+////////////////////////////////////////////////////////////////////////////////
+
+/* detect Linux platform */
+#if defined(linux) || defined(__linux__) || defined(__LINUX__)
+# if !defined(__LINUX__)
+# define __LINUX__
+# endif
+# if !defined(__UNIX__)
+# define __UNIX__
+# endif
+#endif
+
+/* detect FreeBSD platform */
+#if defined(__FreeBSD__) || defined(__FREEBSD__)
+# if !defined(__FREEBSD__)
+# define __FREEBSD__
+# endif
+# if !defined(__UNIX__)
+# define __UNIX__
+# endif
+#endif
+
+/* detect Windows 95/98/NT/2000/XP/Vista/7 platform */
+#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)) && !defined(__CYGWIN__)
+# if !defined(__WIN32__)
+# define __WIN32__
+# endif
+#endif
+
+/* detect Cygwin platform */
+#if defined(__CYGWIN__)
+# if !defined(__UNIX__)
+# define __UNIX__
+# endif
+#endif
+
+/* detect MAC OS X platform */
+#if defined(__APPLE__) || defined(MACOSX) || defined(__MACOSX__)
+# if !defined(__MACOSX__)
+# define __MACOSX__
+# endif
+# if !defined(__UNIX__)
+# define __UNIX__
+# endif
+#endif
+
+/* try to detect other Unix systems */
+#if defined(__unix__) || defined (unix) || defined(__unix) || defined(_unix)
+# if !defined(__UNIX__)
+# define __UNIX__
+# endif
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// Compiler
+////////////////////////////////////////////////////////////////////////////////
+
+/*! GCC compiler */
+#ifdef __GNUC__
+// #define __GNUC__
+#endif
+
+/*! Intel compiler */
+#ifdef __INTEL_COMPILER
+#define __ICC__
+#endif
+
+/*! Visual C compiler */
+#ifdef _MSC_VER
+#define __MSVC__
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// Makros
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __WIN32__
+#define __dllexport extern "C" __declspec(dllexport)
+#define __dllimport extern "C" __declspec(dllimport)
+#else
+#define __dllexport extern "C"
+#define __dllimport extern "C"
+#endif
+
+#ifdef __MSVC__
+#undef NOINLINE
+#define NOINLINE __declspec(noinline)
+#define INLINE __forceinline
+#define RESTRICT __restrict
+#define THREAD __declspec(thread)
+#define ALIGNED(...) __declspec(align(__VA_ARGS__))
+//#define __FUNCTION__ __FUNCTION__
+#define debugbreak() __debugbreak()
+#else
+#undef NOINLINE
+#undef INLINE
+#define NOINLINE __attribute__((noinline))
+#define INLINE inline __attribute__((always_inline))
+#define RESTRICT __restrict
+#define THREAD __thread
+#define ALIGNED(...) __attribute__((aligned(__VA_ARGS__)))
+#define __FUNCTION__ __PRETTY_FUNCTION__
+#define debugbreak() asm ("int $3")
+#endif
+
+/*! Modern x86 processors */
+#define CACHE_LINE 64
+#define CACHE_LINE_ALIGNED ALIGNED(CACHE_LINE)
+
+#ifdef __GNUC__
+ #define MAYBE_UNUSED __attribute__((used))
+#else
+ #define MAYBE_UNUSED
+#endif
+
+#if defined(_MSC_VER)
+#define __builtin_expect(expr,b) expr
+#endif
+
+/*! Debug syntactic sugar */
+#ifdef NDEBUG
+#define IF_DEBUG(EXPR)
+#else
+#define IF_DEBUG(EXPR) EXPR
+#endif /* NDEBUG */
+
+/*! Debug printing macros */
+#define STRING(x) #x
+#define PING std::cout << __FILE__ << " (" << __LINE__ << "): " << __FUNCTION__ << std::endl
+#define PRINT(x) std::cout << STRING(x) << " = " << (x) << std::endl
+
+/*! Branch hint */
+#define LIKELY(x) __builtin_expect(!!(x),1)
+#define UNLIKELY(x) __builtin_expect((x),0)
+
+/*! Stringify macros */
+#define JOIN(X, Y) _DO_JOIN(X, Y)
+#define _DO_JOIN(X, Y) _DO_JOIN2(X, Y)
+#define _DO_JOIN2(X, Y) X##Y
+
+/*! Run-time assertion */
+#ifndef NDEBUG
+#define PF_ASSERT(EXPR) do { \
+ if (UNLIKELY(!(EXPR))) assert(EXPR); \
+} while (0)
+#else
+#define PF_ASSERT(EXPR) do { } while (0)
+#endif
+
+/*! Compile-time assertion */
+#define STATIC_ASSERT(value) \
+ struct JOIN(__,JOIN(__,__LINE__)) { int x[(value) ? 1 : -1]; }
+
+/*! Fatal error macros */
+#define NOT_IMPLEMENTED FATAL ("Not implemented")
+#define FATAL_IF(COND, MSG) \
+do { \
+ if(UNLIKELY(COND)) FATAL(MSG); \
+} while (0)
+
+/* Safe deletion macros */
+#define PF_SAFE_DELETE_ARRAY(x) do { if (x != NULL) PF_DELETE_ARRAY(x); } while (0)
+#define PF_SAFE_DELETE(x) do { if (x != NULL) PF_DELETE(x); } while (0)
+
+/* Number of elements in an array */
+#define ARRAY_ELEM_NUM(x) (sizeof(x) / sizeof(x[0]))
+
+/* Align X on A */
+#define ALIGN(X,A) (((X) % (A)) ? ((X) + (A) - ((X) % (A))) : (X))
+
+/*! Produce a string from the macro locatiom */
+#define HERE (STRING(__LINE__) "@" __FILE__)
+
+/*! Portable AlignOf */
+template <typename T>
+struct AlignOf
+{
+ struct Helper { char x; T t; };
+ static const size_t value = offsetof(Helper, t);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+/// Visibility parameters (DLL export and so on)
+////////////////////////////////////////////////////////////////////////////////
+#if defined __WIN32__
+ #if defined __GNUC__
+ #define PF_EXPORT_SYMBOL __attribute__ ((dllexport))
+ #define PF_IMPORT_SYMBOL __attribute__ ((dllimport))
+ #else
+ #define PF_IMPORT_SYMBOL __declspec(dllimport)
+ #define PF_EXPORT_SYMBOL __declspec(dllexport)
+ #endif /* __GNUC__ */
+#else
+ #define PF_EXPORT_SYMBOL __attribute__ ((visibility ("default")))
+ #define PF_IMPORT_SYMBOL
+#endif /* __WIN32__ */
+
+////////////////////////////////////////////////////////////////////////////////
+/// Basic Types
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__MSVC__)
+typedef __int64 int64;
+typedef unsigned __int64 uint64;
+typedef __int32 int32;
+typedef unsigned __int32 uint32;
+typedef __int16 int16;
+typedef unsigned __int16 uint16;
+typedef __int8 int8;
+typedef unsigned __int8 uint8;
+#else
+typedef long long int64;
+typedef unsigned long long uint64;
+typedef int int32;
+typedef unsigned int uint32;
+typedef short int16;
+typedef unsigned short uint16;
+typedef char int8;
+typedef unsigned char uint8;
+#endif
+
+#if defined(__X86_64__)
+typedef int64 index_t;
+#else
+typedef int32 index_t;
+#endif
+
+/*! To protect some classes from being copied */
+class NonCopyable
+{
+protected:
+ INLINE NonCopyable(void) {}
+ INLINE ~NonCopyable(void) {}
+private:
+ INLINE NonCopyable(const NonCopyable&) {}
+ INLINE NonCopyable& operator= (const NonCopyable&) {return *this;}
+};
+
+////////////////////////////////////////////////////////////////////////////////
+/// Disable some compiler warnings
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __ICC__
+#pragma warning(disable:265) // floating-point operation result is out of range
+#pragma warning(disable:383) // value copied to temporary, reference to temporary used
+#pragma warning(disable:869) // parameter was never referenced
+#pragma warning(disable:981) // operands are evaluated in unspecified order
+#pragma warning(disable:1418) // external function definition with no prior declaration
+#pragma warning(disable:1419) // external declaration in primary source file
+#pragma warning(disable:1572) // floating-point equality and inequality comparisons are unreliable
+#pragma warning(disable:1125) // virtual function override intended?
+#endif /* __ICC__ */
+
+////////////////////////////////////////////////////////////////////////////////
+/// Default Includes and Functions
+////////////////////////////////////////////////////////////////////////////////
+
+#include "sys/constants.hpp"
+#include "sys/alloc.hpp"
+
+namespace pf
+{
+ /*! selects */
+ INLINE bool select(bool s, bool t , bool f) { return s ? t : f; }
+ INLINE int select(bool s, int t, int f) { return s ? t : f; }
+ INLINE float select(bool s, float t, float f) { return s ? t : f; }
+
+ /*! Fatal error function */
+ void FATAL(const std::string&);
+
+ /*! Return the next power of 2 */
+ INLINE uint32 nextHighestPowerOf2(uint32 x) {
+ x--;
+ x |= x >> 1;
+ x |= x >> 2;
+ x |= x >> 4;
+ x |= x >> 8;
+ x |= x >> 16;
+ return ++x;
+ }
+
+ INLINE uint32 logi2(uint32 x) {
+ uint32 r = 0;
+ while(x >>= 1) r++;
+ return r;
+ }
+
+ template<uint32 N>
+ INLINE uint32 isPowerOf(uint32 i) {
+ while (i > 1) {
+ if (i%N) return false;
+ i = i/N;
+ }
+ return true;
+ }
+ template<> INLINE uint32 isPowerOf<2>(uint32 i) { return ((i-1)&i) == 0; }
+
+ /*! random functions */
+ template<typename T> T random() { return T(0); }
+ template<> INLINE int random() { return int(rand()); }
+ template<> INLINE uint32 random() { return uint32(rand()); }
+ template<> INLINE float random() { return random<uint32>()/float(RAND_MAX); }
+ template<> INLINE double random() { return random<uint32>()/double(RAND_MAX); }
+
+ /** returns performance counter in seconds */
+ double getSeconds();
+
+} /* namespace pf */
+
+#endif /* __PF_PLATFORM_HPP__ */
+
diff --git a/backend/src/sys/ref.hpp b/backend/src/sys/ref.hpp
new file mode 100644
index 00000000..1672f543
--- /dev/null
+++ b/backend/src/sys/ref.hpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_REF_HPP__
+#define __PF_REF_HPP__
+
+#include "sys/atomic.hpp"
+#include "sys/alloc.hpp"
+
+namespace pf
+{
+ class RefCount
+ {
+ public:
+ RefCount() : refCounter(0) {}
+ virtual ~RefCount() {}
+ INLINE void refInc() { refCounter++; }
+ INLINE bool refDec() { return !(--refCounter); }
+ Atomic32 refCounter;
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Reference to single object
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename Type>
+ class Ref {
+ public:
+ Type* const ptr;
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ INLINE Ref(void) : ptr(NULL) {}
+ INLINE Ref(NullTy) : ptr(NULL) {}
+ INLINE Ref(const Ref& input) : ptr(input.ptr) { if ( ptr ) ptr->refInc(); }
+ INLINE Ref(Type* const input) : ptr(input) { if (ptr) ptr->refInc(); }
+ INLINE ~Ref(void) { if (ptr && ptr->refDec()) PF_DELETE(ptr); }
+
+ INLINE Ref& operator= (const Ref &input) {
+ if (input.ptr) input.ptr->refInc();
+ if (ptr && ptr->refDec()) PF_DELETE(ptr);
+ *(Type**)&ptr = input.ptr;
+ return *this;
+ }
+
+ INLINE Ref& operator= (NullTy) {
+ if (ptr && ptr->refDec()) DELETE(ptr);
+ *(Type**)&ptr = NULL;
+ return *this;
+ }
+
+ INLINE operator bool(void) const { return ptr != NULL; }
+ INLINE operator Type*(void) const { return ptr; }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Properties
+ ////////////////////////////////////////////////////////////////////////////////
+
+ INLINE const Type& operator* (void) const { return *ptr; }
+ INLINE const Type* operator-> (void) const { return ptr; }
+ INLINE Type& operator* (void) { return *ptr; }
+ INLINE Type* operator-> (void) { return ptr; }
+
+ template<typename TypeOut>
+ INLINE Ref<TypeOut> cast() { return Ref<TypeOut>(static_cast<TypeOut*>(ptr)); }
+ template<typename TypeOut>
+ INLINE const Ref<TypeOut> cast() const { return Ref<TypeOut>(static_cast<TypeOut*>(ptr)); }
+ PF_CLASS(Ref);
+ };
+
+ template<typename Type> INLINE bool operator< ( const Ref<Type>& a, const Ref<Type>& b ) { return a.ptr < b.ptr ; }
+ template<typename Type> INLINE bool operator== ( const Ref<Type>& a, NullTy ) { return a.ptr == NULL ; }
+ template<typename Type> INLINE bool operator== ( NullTy , const Ref<Type>& b ) { return NULL == b.ptr ; }
+ template<typename Type> INLINE bool operator== ( const Ref<Type>& a, const Ref<Type>& b ) { return a.ptr == b.ptr ; }
+ template<typename Type> INLINE bool operator!= ( const Ref<Type>& a, NullTy ) { return a.ptr != NULL ; }
+ template<typename Type> INLINE bool operator!= ( NullTy , const Ref<Type>& b ) { return NULL != b.ptr ; }
+ template<typename Type> INLINE bool operator!= ( const Ref<Type>& a, const Ref<Type>& b ) { return a.ptr != b.ptr ; }
+}
+
+#endif /* __PF_REF_HPP__ */
+
diff --git a/backend/src/sys/set.hpp b/backend/src/sys/set.hpp
new file mode 100644
index 00000000..efaf7ed3
--- /dev/null
+++ b/backend/src/sys/set.hpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_SET_HPP__
+#define __PF_SET_HPP__
+
+#include "sys/platform.hpp"
+#include <set>
+
+namespace pf
+{
+ /*! Add our custom allocator to std::set */
+ template<class Key, class Pred = std::less<Key>>
+ class set : public std::set<Key,Pred,Allocator<Key>>
+ {
+ public:
+ // Typedefs
+ typedef Key value_type;
+ typedef Allocator<value_type> allocator_type;
+ typedef std::set<Key,Pred,Allocator<Key>> parent_type;
+ typedef Key key_type;
+ typedef Pred key_compare;
+
+ /*! Default constructor */
+ INLINE set(const key_compare &comp = key_compare(),
+ const allocator_type &a = allocator_type()) :
+ parent_type(comp, a) {}
+ /*! Iteration constructor */
+ template<class InputIterator>
+ INLINE set(InputIterator first,
+ InputIterator last,
+ const key_compare &comp = key_compare(),
+ const allocator_type& a = allocator_type()) :
+ parent_type(first, last, comp, a) {}
+ /*! Copy constructor */
+ INLINE set(const set& x) : parent_type(x) {}
+ PF_CLASS(set);
+ };
+
+} /* namespace pf */
+
+#endif /* __PF_SET_HPP__ */
+
diff --git a/backend/src/sys/string.cpp b/backend/src/sys/string.cpp
new file mode 100644
index 00000000..093bb267
--- /dev/null
+++ b/backend/src/sys/string.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "sys/string.hpp"
+#include "sys/filename.hpp"
+
+#include <cstdio>
+#include <cctype>
+#include <istream>
+#include <fstream>
+#include <algorithm>
+
+namespace std
+{
+ char to_lower(char c) { return char(tolower(int(c))); }
+ char to_upper(char c) { return char(toupper(int(c))); }
+ string strlwr(const string& s) {
+ string dst(s);
+ std::transform(dst.begin(), dst.end(), dst.begin(), to_lower);
+ return dst;
+ }
+ string strupr(const string& s) {
+ string dst(s);
+ std::transform(dst.begin(), dst.end(), dst.begin(), to_upper);
+ return dst;
+ }
+
+}
+namespace pf
+{
+ /* $Id: strtok_r.c,v 1.1 2003/12/03 15:22:23 chris_reid Exp $ */
+ /*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Hgskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+ char* tokenize(char *s1, const char *s2, char **lasts)
+ {
+ char *ret;
+
+ if (s1 == NULL)
+ s1 = *lasts;
+ while(*s1 && strchr(s2, *s1))
+ ++s1;
+ if(*s1 == '\0')
+ return NULL;
+ ret = s1;
+ while(*s1 && !strchr(s2, *s1))
+ ++s1;
+ if(*s1)
+ *s1++ = '\0';
+ *lasts = s1;
+ return ret;
+ }
+
+ bool strequal(const char *s1, const char *s2) {
+ if (strcmp(s1, s2) == 0) return true;
+ return false;
+ }
+
+ bool contains(const char *haystack, const char *needle) {
+ if (strstr(haystack, needle) == NULL) return false;
+ return true;
+ }
+
+ std::string loadFile(const FileName &path)
+ {
+ std::ifstream stream(path.c_str(), std::istream::in);
+ if (stream.is_open() == false)
+ return std::string();
+ std::string str = loadFile(stream);
+ stream.close();
+ return str;
+ }
+
+ std::string loadFile(std::ifstream &stream)
+ {
+ PF_ASSERT(stream.is_open());
+ std::string line;
+ std::stringstream text;
+ while (std::getline(stream, line))
+ text << "\n" << line;
+ stream.close();
+ return text.str();
+ }
+}
+
diff --git a/backend/src/sys/string.hpp b/backend/src/sys/string.hpp
new file mode 100644
index 00000000..04479667
--- /dev/null
+++ b/backend/src/sys/string.hpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_STRING_H__
+#define __PF_STRING_H__
+
+#include "sys/platform.hpp"
+#include "sys/filename.hpp"
+
+#include <cstring>
+#include <string>
+#include <sstream>
+#include <fstream>
+
+namespace std
+{
+ string strlwr(const string& s);
+ string strupr(const string& s);
+
+ template<typename T> INLINE string stringOf(const T& v) {
+ stringstream s; s << v; return s.str();
+ }
+}
+namespace pf
+{
+ /*! Compare two strings */
+ bool strequal(const char *s1, const char *s2);
+ /*! Say if needle is in haystack */
+ bool contains(const char *haystack, const char *needle);
+ /*! Tokenize a string (like strtok_r does) */
+ char* tokenize(char *s1, const char *s2, char **lasts);
+ /*! Load a file from its path and copies it into a string */
+ std::string loadFile(const FileName &path);
+ /*! Load a file from a stream and copies it into a string */
+ std::string loadFile(std::ifstream &stream);
+}
+#endif
diff --git a/backend/src/sys/sysinfo.cpp b/backend/src/sys/sysinfo.cpp
new file mode 100644
index 00000000..15a56095
--- /dev/null
+++ b/backend/src/sys/sysinfo.cpp
@@ -0,0 +1,148 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "sys/sysinfo.hpp"
+
+////////////////////////////////////////////////////////////////////////////////
+/// All Platforms
+////////////////////////////////////////////////////////////////////////////////
+
+namespace pf
+{
+ /* return platform name */
+ std::string getPlatformName() {
+#if defined(__LINUX__) && !defined(__X86_64__)
+ return "Linux (32bit)";
+#elif defined(__LINUX__) && defined(__X86_64__)
+ return "Linux (64bit)";
+#elif defined(__FREEBSD__) && !defined(__X86_64__)
+ return "FreeBSD (32bit)";
+#elif defined(__FREEBSD__) && defined(__X86_64__)
+ return "FreeBSD (64bit)";
+#elif defined(__CYGWIN__) && !defined(__X86_64__)
+ return "Cygwin (32bit)";
+#elif defined(__CYGWIN__) && defined(__X86_64__)
+ return "Cygwin (64bit)";
+#elif defined(__WIN32__) && !defined(__X86_64__)
+ return "Windows (32bit)";
+#elif defined(__WIN32__) && defined(__X86_64__)
+ return "Windows (64bit)";
+#elif defined(__MACOSX__) && !defined(__X86_64__)
+ return "MacOS (32bit)";
+#elif defined(__MACOSX__) && defined(__X86_64__)
+ return "MacOS (64bit)";
+#elif defined(__UNIX__) && !defined(__X86_64__)
+ return "Unix (32bit)";
+#elif defined(__UNIX__) && defined(__X86_64__)
+ return "Unix (64bit)";
+#else
+ return "Unknown";
+#endif
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// Windows Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __WIN32__
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+namespace pf
+{
+ /* get the full path to the running executable */
+ std::string getExecutableFileName() {
+ char filename[1024];
+ if (!GetModuleFileName(NULL, filename, sizeof(filename))) return std::string();
+ return std::string(filename);
+ }
+
+ /* return the number of logical threads of the system */
+ int getNumberOfLogicalThreads() {
+ SYSTEM_INFO sysinfo;
+ GetSystemInfo(&sysinfo);
+ return sysinfo.dwNumberOfProcessors;
+ }
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// Linux Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __LINUX__
+
+#include <stdio.h>
+#include <unistd.h>
+
+namespace pf
+{
+ /* get the full path to the running executable */
+ std::string getExecutableFileName() {
+ char pid[32]; sprintf(pid, "/proc/%d/exe", getpid());
+ char buf[1024];
+ int bytes = readlink(pid, buf, sizeof(buf)-1);
+ if (bytes != -1) buf[bytes] = '\0';
+ return std::string(buf);
+ }
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// MacOS Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __MACOSX__
+
+#include <mach-o/dyld.h>
+
+namespace pf
+{
+ /* get the full path to the running executable */
+ std::string getExecutableFileName()
+ {
+ char buf[1024];
+ uint32_t size = sizeof(buf);
+ if (_NSGetExecutablePath(buf, &size) != 0) return std::string();
+ return std::string(buf);
+ }
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// Unix Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__UNIX__)
+
+#include <unistd.h>
+
+namespace pf
+{
+ /* return the number of logical threads of the system */
+ int getNumberOfLogicalThreads() {
+ return sysconf(_SC_NPROCESSORS_CONF);
+ }
+}
+#endif
+
diff --git a/backend/src/sys/sysinfo.hpp b/backend/src/sys/sysinfo.hpp
new file mode 100644
index 00000000..5679ddb0
--- /dev/null
+++ b/backend/src/sys/sysinfo.hpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_SYSINFO_H__
+#define __PF_SYSINFO_H__
+
+#include "sys/platform.hpp"
+
+#include <string>
+
+namespace pf
+{
+ /*! get the full path to the running executable */
+ std::string getExecutableFileName();
+ /*! return platform name */
+ std::string getPlatformName();
+ /*! return the number of logical threads of the system */
+ int getNumberOfLogicalThreads();
+}
+
+#endif
diff --git a/backend/src/sys/thread.cpp b/backend/src/sys/thread.cpp
new file mode 100644
index 00000000..12503ce3
--- /dev/null
+++ b/backend/src/sys/thread.cpp
@@ -0,0 +1,213 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include <iostream>
+
+#include "sys/thread.hpp"
+#include "sys/sysinfo.hpp"
+
+////////////////////////////////////////////////////////////////////////////////
+/// Windows Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __WIN32__
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+namespace pf
+{
+ /*! creates a hardware thread running on specific core */
+ thread_t createThread(thread_func f, void* arg, size_t stack_size, int affinity)
+ {
+ HANDLE handle = CreateThread(NULL,stack_size,(LPTHREAD_START_ROUTINE)f,arg,0,NULL);
+ if (handle == NULL)
+ FATAL("createThread error");
+ if (affinity < 0) return thread_t(handle);
+
+ // set thread affinity
+ int thread = affinity % 64;
+ SetThreadAffinityMask(handle, DWORD_PTR(1L << thread));
+
+ return thread_t(handle);
+ }
+
+ void setAffinity(int affinity) {
+ if (affinity >= 0) SetThreadAffinityMask(GetCurrentThread(), DWORD_PTR(1L << affinity));
+ }
+
+ void yield(int time) { Sleep(time); }
+
+ void join(thread_t tid) {
+ WaitForSingleObject(HANDLE(tid), INFINITE);
+ CloseHandle(HANDLE(tid));
+ }
+
+ void destroyThread(thread_t tid) {
+ TerminateThread(HANDLE(tid),0);
+ CloseHandle(HANDLE(tid));
+ }
+
+ tls_t createTls() { return tls_t(TlsAlloc()); }
+
+ void setTls(tls_t tls, void* const ptr) {
+ TlsSetValue(DWORD(size_t(tls)), ptr);
+ }
+
+ void* getTls(tls_t tls) {
+ return TlsGetValue(DWORD(size_t(tls)));
+ }
+
+ void destroyTls(tls_t tls) {
+ TlsFree(DWORD(size_t(tls)));
+ }
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// Linux Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __LINUX__
+namespace pf
+{
+ /*! set affinity of the calling thread */
+ void setAffinity(int affinity)
+ {
+ int wrap = getNumberOfLogicalThreads()/2;
+ affinity = (affinity/2) + wrap*(affinity%2);
+ if (affinity >= 0 && affinity < 64*64) {
+ union { uint64 u; cpu_set_t set; } mask[64];
+ for (size_t i=0; i<64; i++) mask[i].u = 0;
+ mask[affinity/64].u= uint64(1) << (affinity % 64);
+ if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask[0].set) < 0)
+ std::cerr << "Thread: cannot set affinity" << std::endl;
+ }
+ }
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// MacOSX Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __MACOSX__
+
+#include <mach/thread_act.h>
+#include <mach/thread_policy.h>
+#include <mach/mach_init.h>
+
+namespace pf
+{
+ /*! set affinity of the calling thread */
+ void setAffinity(int affinity)
+ {
+ if (affinity >= 0) {
+ thread_affinity_policy ap;
+ ap.affinity_tag = affinity;
+ if (thread_policy_set(mach_thread_self(),THREAD_AFFINITY_POLICY,(integer_t*)&ap,THREAD_AFFINITY_POLICY_COUNT) != KERN_SUCCESS)
+ std::cerr << "Thread: cannot set affinity" << std::endl;
+ }
+ }
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// Unix Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __UNIX__
+
+#include <pthread.h>
+#include <sched.h>
+
+namespace pf
+{
+ struct ThreadStartupData {
+ int affinity;
+ thread_func f;
+ void* arg;
+ };
+
+ static void* threadStartup(ThreadStartupData* parg)
+ {
+ ThreadStartupData arg = *parg; PF_DELETE(parg); parg = NULL;
+ setAffinity(arg.affinity);
+ arg.f(arg.arg);
+ return NULL;
+ }
+
+ thread_t createThread(thread_func f, void* arg, size_t stack_size, int affinity)
+ {
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ if (stack_size > 0) pthread_attr_setstacksize (&attr, stack_size);
+
+ pthread_t* tid = PF_NEW(pthread_t);
+ ThreadStartupData* startup = PF_NEW(ThreadStartupData);
+ startup->f = f;
+ startup->arg = arg;
+ startup->affinity = affinity;
+
+ if (pthread_create(tid,&attr,(void*(*)(void*))threadStartup,startup) != 0)
+ FATAL("Thread creation error");
+
+ return thread_t(tid);
+ }
+
+ void yield(int time) {
+ if (time == 0) sched_yield();
+ else usleep(time * 1000);
+ }
+
+ void join(thread_t tid) {
+ if (pthread_join(*(pthread_t*)tid, NULL) != 0)
+ FATAL("pthread_join error");
+ PF_DELETE((pthread_t*)tid);
+ }
+
+ void destroyThread(thread_t tid) {
+ pthread_cancel(*(pthread_t*)tid);
+ PF_DELETE((pthread_t*)tid);
+ }
+
+ tls_t createTls() {
+ pthread_key_t* key = PF_NEW(pthread_key_t);
+ if (pthread_key_create(key,NULL) != 0)
+ FATAL("pthread_key_create error");
+ return tls_t(key);
+ }
+
+ void* getTls(tls_t tls) {
+ return pthread_getspecific(*(pthread_key_t*)tls);
+ }
+
+ void setTls(tls_t tls, void* const ptr) {
+ if (pthread_setspecific(*(pthread_key_t*)tls, ptr) != 0)
+ FATAL("pthread_setspecific error");
+ }
+
+ void destroyTls(tls_t tls) {
+ if (pthread_key_delete(*(pthread_key_t*)tls) != 0)
+ FATAL("pthread_key_delete error");
+ PF_DELETE((pthread_key_t*)tls);
+ }
+}
+#endif
diff --git a/backend/src/sys/thread.hpp b/backend/src/sys/thread.hpp
new file mode 100644
index 00000000..0611ef72
--- /dev/null
+++ b/backend/src/sys/thread.hpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_THREAD_HPP__
+#define __PF_THREAD_HPP__
+
+#include "sys/platform.hpp"
+
+namespace pf
+{
+ /*! Type for thread */
+ typedef struct opaque_thread_t* thread_t;
+ /*! Signature of thread start function */
+ typedef void (*thread_func)(void*);
+ /*! Creates a hardware thread running on specific logical thread */
+ thread_t createThread(thread_func f, void* arg, size_t stack_size = 0, int affinity = -1);
+ /*! Set affinity of the calling thread */
+ void setAffinity(int affinity);
+ /*! The thread calling this function gets yielded for a number of seconds */
+ void yield(int time = 0);
+ /*! Waits until the given thread has terminated */
+ void join(thread_t tid);
+ /*! Destroy handle of a thread */
+ void destroyThread(thread_t tid);
+ /*! Type for handle to thread local storage */
+ typedef struct opaque_tls_t* tls_t;
+ /*! Creates thread local storage */
+ tls_t createTls();
+ /*! Set the thread local storage pointer */
+ void setTls(tls_t tls, void* const ptr);
+ /*! Return the thread local storage pointer */
+ void* getTls(tls_t tls);
+ /*! Destroys thread local storage identifier */
+ void destroyTls(tls_t tls);
+}
+
+#endif /* __PF_THREAD_HPP__ */
+
diff --git a/backend/src/sys/vector.hpp b/backend/src/sys/vector.hpp
new file mode 100644
index 00000000..a100770d
--- /dev/null
+++ b/backend/src/sys/vector.hpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_VECTOR_HPP__
+#define __PF_VECTOR_HPP__
+
+#include "sys/platform.hpp"
+#include <vector>
+
+namespace pf
+{
+ /*! Add bound checks to the standard vector class and use the internal
+ * allocator
+ */
+ template<class T>
+ class vector : public std::vector<T, Allocator<T>>
+ {
+ public:
+ // Typedefs
+ typedef std::vector<T, Allocator<T>> parent_type;
+ typedef Allocator<T> allocator_type;
+ typedef typename allocator_type::size_type size_type;
+ typedef typename parent_type::iterator iterator;
+
+ /*! Default constructor */
+ INLINE explicit vector(const allocator_type &a = allocator_type()) :
+ parent_type(a) {}
+ /*! Copy constructor */
+ INLINE vector(const vector &x) : parent_type(x) {}
+ /*! Repetitive sequence constructor */
+ INLINE explicit vector(size_type n,
+ const T& value= T(),
+ const allocator_type &a = allocator_type()) :
+ parent_type(n, value, a) {}
+ /*! Iteration constructor */
+ template <class InputIterator>
+ INLINE vector(InputIterator first,
+ InputIterator last,
+ const allocator_type &a = allocator_type()) :
+ parent_type(first, last, a) {}
+ /*! Get element at position index (with a bound check) */
+ T &operator[] (size_t index) {
+ PF_ASSERT(index < this->size());
+ return parent_type::operator[] (index);
+ }
+ /*! Get element at position index (with a bound check) */
+ const T &operator[] (size_t index) const {
+ PF_ASSERT(index < this->size());
+ return parent_type::operator[] (index);
+ }
+ PF_CLASS(vector);
+ };
+} /* namespace pf */
+
+#endif /* __PF_VECTOR_HPP__ */
+
diff --git a/backend/src/utest/utest.cpp b/backend/src/utest/utest.cpp
new file mode 100644
index 00000000..8fca9682
--- /dev/null
+++ b/backend/src/utest/utest.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "utest.hpp"
+#include "sys/string.hpp"
+
+namespace pf
+{
+ std::vector<UTest> *UTest::utestList = NULL;
+ void releaseUTestList(void) { if (UTest::utestList) delete UTest::utestList; }
+
+ UTest::UTest(Function fn, const char *name) : fn(fn), name(name) {
+ if (utestList == NULL) {
+ utestList = new std::vector<UTest>;
+ atexit(releaseUTestList);
+ }
+ utestList->push_back(*this);
+ }
+
+ UTest::UTest(void) : fn(NULL), name(NULL) {}
+
+ void UTest::run(const char *name) {
+ if (name == NULL) return;
+ if (utestList == NULL) return;
+ for (size_t i = 0; i < utestList->size(); ++i) {
+ const UTest &utest = (*utestList)[i];
+ if (utest.name == NULL || utest.fn == NULL) continue;
+ if (strequal(utest.name, name)) (utest.fn)();
+ }
+ }
+
+ void UTest::runAll(void) {
+ if (utestList == NULL) return;
+ for (size_t i = 0; i < utestList->size(); ++i) {
+ const UTest &utest = (*utestList)[i];
+ if (utest.fn == NULL) continue;
+ (utest.fn)();
+ }
+ }
+} /* namespace pf */
+
diff --git a/backend/src/utest/utest.hpp b/backend/src/utest/utest.hpp
new file mode 100644
index 00000000..fea1bbcd
--- /dev/null
+++ b/backend/src/utest/utest.hpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_UTEST_HPP__
+#define __PF_UTEST_HPP__
+
+#include <vector>
+
+namespace pf
+{
+ /*! Quick and dirty Unit test system with registration */
+ struct UTest
+ {
+ /*! A unit test function to run */
+ typedef void (*Function) (void);
+ /*! Empty test */
+ UTest(void);
+ /*! Build a new unit test and append it to the unit test list */
+ UTest(Function fn, const char *name);
+ /*! Function to execute */
+ Function fn;
+ /*! Name of the test */
+ const char *name;
+ /*! The tests that are registered */
+ static std::vector<UTest> *utestList;
+ /*! Run the test with the given name */
+ static void run(const char *name);
+ /*! Run all the tests */
+ static void runAll(void);
+ };
+} /* namespace pf */
+
+/*! Register a new unit test */
+#define UTEST_REGISTER(FN) static const pf::UTest __##NAME##__(FN, #FN);
+
+#endif /* __PF_UTEST_HPP__ */
+
diff --git a/backend/src/utest/utest_console.cpp b/backend/src/utest/utest_console.cpp
new file mode 100644
index 00000000..51075944
--- /dev/null
+++ b/backend/src/utest/utest_console.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "utest/utest.hpp"
+#include "sys/command.hpp"
+#include "sys/console.hpp"
+#include "sys/logging.hpp"
+#include "sys/windowing.hpp"
+#include "sys/script.hpp"
+#include <string>
+
+namespace pf
+{
+ /*! Output everything in the terminal */
+ class UTestConsoleDisplay : public ConsoleDisplay
+ {
+ public:
+ UTestConsoleDisplay (void) {
+ last = lastBlink = getSeconds();
+ cursor = 0;
+ }
+ virtual void line(Console &console, const std::string &line) {
+ const double curr = getSeconds();
+ std::string patched = line;
+ if (curr - lastBlink > .5) {
+ cursor ^= 1;
+ lastBlink = curr;
+ }
+ const uint32 pos = console.cursorPosition();
+ if (cursor) {
+ if (pos >= patched.size())
+ patched.push_back('_');
+ else
+ patched[pos] = '_';
+ }
+ if (curr - last > 0.02) {
+ std::cout << '\r' << "> " << patched;
+ for (int i = 0; i < 80; ++i) std::cout << ' ';
+ std::cout << '\r';
+ fflush(stdout);
+ last = curr;
+ }
+ }
+ virtual void out(Console &console, const std::string &str) {
+ std::cout << str << std::endl;
+ }
+ double last;
+ double lastBlink;
+ uint32 cursor;
+ };
+} /* namespace pf */
+
+void utest_console(void)
+{
+ using namespace pf;
+ WinOpen(640, 480);
+ ScriptSystem *scriptSystem = LuaScriptSystemCreate();
+ CommandSystemStart(*scriptSystem);
+ UTestConsoleDisplay *display = PF_NEW(UTestConsoleDisplay);
+ Console *console = ConsoleNew(*scriptSystem, *display);
+ console->addCompletion("while");
+ console->addCompletion("whilewhile");
+ for (;;) {
+ Ref<InputControl> input = PF_NEW(InputControl);
+ input->processEvents();
+ if (input->getKey(PF_KEY_ASCII_ESC))
+ break;
+ console->update(*input);
+ WinSwapBuffers();
+ }
+ CommandSystemEnd();
+ PF_DELETE(console);
+ PF_DELETE(scriptSystem);
+ PF_DELETE(display);
+ WinClose();
+}
+
+UTEST_REGISTER(utest_console);
+
diff --git a/backend/src/utest/utest_font.cpp b/backend/src/utest/utest_font.cpp
new file mode 100644
index 00000000..d6b0fa9f
--- /dev/null
+++ b/backend/src/utest/utest_font.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "renderer/font.hpp"
+#include "sys/default_path.hpp"
+#include "utest/utest.hpp"
+
+#include <string>
+
+using namespace pf;
+static const std::string fontName = "font.fnt";
+
+void utest_font(void)
+{
+ Font font;
+ size_t i = 0;
+ for (; i < defaultPathNum; ++i) {
+ const FileName path(std::string(defaultPath[i]) + fontName);
+ if (font.load(path)) break;
+ }
+ PF_ASSERT(i < defaultPathNum);
+}
+
+UTEST_REGISTER(utest_font);
+
diff --git a/backend/src/utest/utest_lua.cpp b/backend/src/utest/utest_lua.cpp
new file mode 100644
index 00000000..289ef7f3
--- /dev/null
+++ b/backend/src/utest/utest_lua.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "sys/script.hpp"
+#include "sys/command.hpp"
+#include "sys/logging.hpp"
+#include "sys/tasking.hpp"
+#include "utest/utest.hpp"
+
+using namespace pf;
+
+VARI(coucou, 0, 2, 3, "coucou");
+VARS(player0, "ben", "player name");
+
+#define _RUN_SCRIPT(STR, RUN_MODE) do {\
+ ScriptStatus status;\
+ scriptSystem->RUN_MODE(STR, status);\
+ if (!status.success) PF_ERROR(status.msg);\
+} while (0)
+#define RUN(STR) _RUN_SCRIPT(STR,run)
+#define RUN_NON_PROTECTED(STR) _RUN_SCRIPT(STR,runNonProtected)
+
+void utest_lua(void)
+{
+ ScriptSystem *scriptSystem = LuaScriptSystemCreate();
+ ScriptStatus status;
+ scriptSystem->run("local x = 0", status);
+ CommandSystemStart(*scriptSystem);
+
+ // Run some code. This may modify console variables
+ RUN("cv.coucou = 1");
+ RUN_NON_PROTECTED("print(pf.cv.coucou)");
+ RUN("cv.player0 = \"hop\"");
+ RUN_NON_PROTECTED("print(pf.cv.player0)");
+ if (coucou() == 1) PF_MSG("coucou is equal to 1");
+
+ CommandSystemEnd();
+ PF_DELETE(scriptSystem);
+}
+
+UTEST_REGISTER(utest_lua)
+
diff --git a/backend/src/utest/utest_rt.cpp b/backend/src/utest/utest_rt.cpp
new file mode 100644
index 00000000..cf2db0ab
--- /dev/null
+++ b/backend/src/utest/utest_rt.cpp
@@ -0,0 +1,193 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "renderer/renderer_obj.hpp"
+#include "renderer/renderer.hpp"
+#include "rt/bvh2_traverser.hpp"
+#include "rt/bvh2.hpp"
+#include "rt/rt_triangle.hpp"
+#include "rt/rt_camera.hpp"
+#include "models/obj.hpp"
+#include "game/camera.hpp"
+#include "image/stb_image.hpp"
+
+#include "sys/alloc.hpp"
+#include "sys/tasking.hpp"
+#include "sys/tasking_utility.hpp"
+#include "sys/logging.hpp"
+#include "sys/default_path.hpp"
+
+#include "utest/utest.hpp"
+
+#include <cstring>
+#include <GL/freeglut.h>
+#include <cstdio>
+#include <iostream>
+
+namespace pf
+{
+ static Ref<Intersector> intersector = NULL;
+ static const int CAMW = 1024, CAMH = 1024;
+
+ static const FileName objName("f000.obj");
+ //static const FileName objName("arabic_city_II.obj");
+ //static const FileName objName("conference.obj");
+ //static const FileName objName("sibenik.obj");
+ //static const FileName objName("sponza.obj");
+
+ static RTTriangle *ObjComputeTriangle(const Obj &obj) {
+ RTTriangle *tris = PF_NEW_ARRAY(RTTriangle, obj.triNum);
+ for (size_t i = 0; i < obj.triNum; ++i) {
+ const vec3f &v0 = obj.vert[obj.tri[i].v[0]].p;
+ const vec3f &v1 = obj.vert[obj.tri[i].v[1]].p;
+ const vec3f &v2 = obj.vert[obj.tri[i].v[2]].p;
+ tris[i] = RTTriangle(v0,v1,v2);
+ }
+ return tris;
+ }
+
+ /*! Task set that computes a frame buffer with ray tracing */
+ template <bool singleRay>
+ class TaskRayTrace : public TaskSet
+ {
+ public:
+ INLINE TaskRayTrace(const Intersector &intersector,
+ const RTCamera &cam,
+ const uint32 *c,
+ uint32 *rgba,
+ uint32 w, uint32 jobNum) :
+ TaskSet(jobNum, "TaskRayTrace"),
+ intersector(intersector), cam(cam), c(c), rgba(rgba),
+ w(w), h(jobNum * RayPacket::height) {}
+
+ virtual void run(size_t jobID)
+ {
+ if (singleRay) {
+ RTCameraRayGen gen;
+ cam.createGenerator(gen, w, h);
+ for (uint32 row = 0; row < RayPacket::height; ++row) {
+ const uint32 y = row + jobID * RayPacket::height;
+ for (uint32 x = 0; x < w; ++x) {
+ Ray ray;
+ Hit hit;
+ gen.generate(ray, x, y);
+ intersector.traverse(ray, hit);
+ rgba[x + y*w] = hit ? c[hit.id0] : 0u;
+ }
+ }
+ } else {
+ RTCameraPacketGen gen;
+ cam.createGenerator(gen, w, h);
+ const uint32 y = jobID * RayPacket::height;
+ for (uint32 x = 0; x < w; x += RayPacket::width) {
+ RayPacket pckt;
+ PacketHit hit;
+ gen.generate(pckt, x, y);
+ intersector.traverse(pckt, hit);
+ const int32 *IDs = (const int32 *) &hit.id0[0][0];
+ uint32 curr = 0;
+ for (uint32 j = 0; j < pckt.height; ++j) {
+ for (uint32 i = 0; i < pckt.width; ++i, ++curr) {
+ const uint32 offset = x + i + (y + j) * w;
+ rgba[offset] = IDs[curr] != -1 ? c[IDs[curr]] : 0u;
+ }
+ }
+ }
+ }
+ }
+
+ const Intersector &intersector; //!< To traverse the scene
+ const RTCamera &cam; //!< Parameterize the view
+ const uint32 *c; //!< One color per triangle
+ uint32 *rgba; //!< Frame buffer
+ uint32 w, h; //!< Frame buffer dimensions
+ };
+
+ /*! Ray trace the loaded scene */
+ template <bool singleRay>
+ static void rayTrace(int w, int h, const uint32 *c) {
+ FPSCamera fpsCam;
+ const RTCamera cam(fpsCam.org, fpsCam.up, fpsCam.view, fpsCam.fov, fpsCam.ratio);
+ uint32 *rgba = PF_NEW_ARRAY(uint32, w * h);
+ std::memset(rgba, 0, sizeof(uint32) * w * h);
+ PF_COMPILER_READ_WRITE_BARRIER;
+ const double t = getSeconds();
+ Task *rayTask = PF_NEW(TaskRayTrace<singleRay>, *intersector,
+ cam, c, rgba, w, h/RayPacket::height);
+ Task *returnToMain = PF_NEW(TaskInterruptMain);
+ rayTask->starts(returnToMain);
+ rayTask->scheduled();
+ returnToMain->scheduled();
+ TaskingSystemEnter();
+ const double dt = getSeconds() - t;
+ PF_MSG_V(dt * 1000. << " msec - " << CAMW * CAMH / dt << " rays/s");
+ if (singleRay)
+ stbi_write_bmp("single.bmp", w, h, 4, rgba);
+ else
+ stbi_write_bmp("packet.bmp", w, h, 4, rgba);
+ PF_DELETE_ARRAY(rgba);
+ }
+
+ static void RTStart(void)
+ {
+ Obj obj;
+ size_t path = 0;
+ for (path = 0; path < defaultPathNum; ++path)
+ if (obj.load(FileName(defaultPath[path]) + objName)) {
+ PF_MSG_V("Obj: " << objName << " loaded from " << defaultPath[path]);
+ break;
+ }
+ if (path == defaultPathNum)
+ PF_WARNING_V("Obj: " << objName << " not found");
+
+ // Build the BVH
+ RTTriangle *tris = ObjComputeTriangle(obj);
+ Ref<BVH2<RTTriangle>> bvh = PF_NEW(BVH2<RTTriangle>);
+ buildBVH2(tris, obj.triNum, *bvh);
+ PF_DELETE_ARRAY(tris);
+
+ // Now we have an intersector on the triangle soup
+ intersector = PF_NEW(BVH2Traverser<RTTriangle>, bvh);
+
+ // Compute some triangle color
+ uint32 *c = PF_NEW_ARRAY(uint32, bvh->primNum);
+ for (uint32 i = 0; i < bvh->primNum; ++i) {
+ c[i] = rand();
+ c[i] |= 0xff000000;
+ }
+
+ // Ray trace now
+ PF_MSG_V("Packet ray tracing");
+ for (int i = 0; i < 16; ++i) rayTrace<false>(CAMW, CAMH, c);
+ PF_MSG_V("Single ray tracing");
+ for (int i = 0; i < 16; ++i) rayTrace<true>(CAMW, CAMH, c);
+ PF_DELETE_ARRAY(c);
+ }
+
+ static void RTEnd(void) { intersector = NULL; }
+}
+
+void utest_rt(void)
+{
+ using namespace pf;
+ RTStart();
+ RTEnd();
+}
+
+UTEST_REGISTER(utest_rt);
diff --git a/backend/src/utest/utest_tasking.cpp b/backend/src/utest/utest_tasking.cpp
new file mode 100644
index 00000000..419c3d73
--- /dev/null
+++ b/backend/src/utest/utest_tasking.cpp
@@ -0,0 +1,653 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "sys/tasking.hpp"
+#include "sys/tasking_utility.hpp"
+#include "sys/ref.hpp"
+#include "sys/thread.hpp"
+#include "sys/mutex.hpp"
+#include "sys/sysinfo.hpp"
+#include "math/random.hpp"
+
+#include "utest/utest.hpp"
+
+#define START_UTEST(TEST_NAME) \
+void TEST_NAME(void) \
+{ \
+ std::cout << std::endl << "starting " << \
+ #TEST_NAME << std::endl;
+
+#define END_UTEST(TEST_NAME) \
+ std::cout << "ending " << #TEST_NAME << std::endl; \
+}
+
+using namespace pf;
+
+///////////////////////////////////////////////////////////////////////////////
+// Very simple test which basically does nothing
+///////////////////////////////////////////////////////////////////////////////
+class TaskDone : public Task {
+public:
+ virtual Task* run(void) {
+ TaskingSystemInterruptMain();
+ return NULL;
+ }
+};
+
+START_UTEST(TestDummy)
+ Task *done = PF_NEW(TaskDone);
+ Task *nothing = PF_NEW(TaskDummy);
+ nothing->starts(done);
+ done->scheduled();
+ nothing->scheduled();
+ TaskingSystemEnter();
+END_UTEST(TestDummy)
+
+///////////////////////////////////////////////////////////////////////////////
+// Simplest taskset test. An array is filled by each worker
+///////////////////////////////////////////////////////////////////////////////
+class TaskSetSimple : public TaskSet {
+public:
+ INLINE TaskSetSimple(size_t elemNum, uint32 *array_) :
+ TaskSet(elemNum), array(array_) {}
+ virtual void run(size_t elemID) { array[elemID] = 1u; }
+ uint32 *array;
+};
+
+START_UTEST(TestTaskSet)
+ const size_t elemNum = 1 << 20;
+ uint32 *array = PF_NEW_ARRAY(uint32, elemNum);
+ for (size_t i = 0; i < elemNum; ++i) array[i] = 0;
+ double t = getSeconds();
+ Task *done = PF_NEW(TaskDone);
+ Task *taskSet = PF_NEW(TaskSetSimple, elemNum, array);
+ taskSet->starts(done);
+ done->scheduled();
+ taskSet->scheduled();
+ TaskingSystemEnter();
+ t = getSeconds() - t;
+ std::cout << t * 1000. << " ms" << std::endl;
+ for (size_t i = 0; i < elemNum; ++i)
+ FATAL_IF(array[i] == 0, "TestTaskSet failed");
+ PF_DELETE_ARRAY(array);
+END_UTEST(TestTaskSet)
+
+///////////////////////////////////////////////////////////////////////////////
+// We create a binary tree of tasks here. Each task spawn a two children upto a
+// given maximum level. Then, a atomic value is updated per leaf. In that test,
+// all tasks complete the ROOT directly
+///////////////////////////////////////////////////////////////////////////////
+enum { maxLevel = 20u };
+
+/*! One node task per node in the tree. Task completes the root */
+class TaskNode : public Task {
+public:
+ INLINE TaskNode(Atomic &value_, uint32 lvl_, Task *root_=NULL) :
+ value(value_), lvl(lvl_) {
+ this->root = root_ == NULL ? this : root_;
+ }
+ virtual Task* run(void);
+ Atomic &value;
+ Task *root;
+ uint32 lvl;
+};
+
+Task* TaskNode::run(void) {
+ if (this->lvl == maxLevel)
+ this->value++;
+ else {
+ Task *left = PF_NEW(TaskNode, this->value, this->lvl+1, this->root);
+ Task *right = PF_NEW(TaskNode, this->value, this->lvl+1, this->root);
+ left->ends(this->root);
+ right->ends(this->root);
+ left->scheduled();
+ right->scheduled();
+ }
+ return NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Same as TaskNode but we use a continuation passing style strategy to improve
+// the system throughtput
+///////////////////////////////////////////////////////////////////////////////
+
+/*! One node task per node in the tree. Task completes the root */
+class TaskNodeOpt : public Task {
+public:
+ INLINE TaskNodeOpt(Atomic &value_, uint32 lvl_, Task *root_=NULL) :
+ value(value_), lvl(lvl_) {
+ this->root = root_ == NULL ? this : root_;
+ }
+ virtual Task* run(void);
+ Atomic &value;
+ Task *root;
+ uint32 lvl;
+};
+
+Task* TaskNodeOpt::run(void) {
+ if (this->lvl == maxLevel) {
+ this->value++;
+ return NULL;
+ } else {
+ Task *left = PF_NEW(TaskNode, this->value, this->lvl+1, this->root);
+ Task *right = PF_NEW(TaskNode, this->value, this->lvl+1, this->root);
+ left->ends(this->root);
+ right->ends(this->root);
+ left->scheduled();
+ return right;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Same as TaskNode but here each task completes its parent task directly. This
+// stresses the completion system but strongly limits cache line contention
+///////////////////////////////////////////////////////////////////////////////
+
+/*! One node task per node in the tree. Task completes its parent */
+class TaskCascadeNode : public Task {
+public:
+ INLINE TaskCascadeNode(Atomic &value_, uint32 lvl_, Task *root_=NULL) :
+ value(value_), lvl(lvl_) {}
+ virtual Task* run(void);
+ Atomic &value;
+ uint32 lvl;
+};
+
+Task *TaskCascadeNode::run(void) {
+ if (this->lvl == maxLevel)
+ this->value++;
+ else {
+ Task *left = PF_NEW(TaskCascadeNode, this->value, this->lvl+1);
+ Task *right = PF_NEW(TaskCascadeNode, this->value, this->lvl+1);
+ left->ends(this);
+ right->ends(this);
+ left->scheduled();
+ right->scheduled();
+ }
+ return NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Same as TaskCascadeNode but with continuation passing style tasks
+///////////////////////////////////////////////////////////////////////////////
+class TaskCascadeNodeOpt : public Task {
+public:
+ INLINE TaskCascadeNodeOpt(Atomic &value_, uint32 lvl_, Task *root_=NULL) :
+ value(value_), lvl(lvl_) {}
+ virtual Task* run(void);
+ Atomic &value;
+ uint32 lvl;
+};
+
+Task *TaskCascadeNodeOpt::run(void) {
+ if (this->lvl == maxLevel) {
+ this->value++;
+ return NULL;
+ } else {
+ Task *left = PF_NEW(TaskCascadeNode, this->value, this->lvl+1);
+ Task *right = PF_NEW(TaskCascadeNode, this->value, this->lvl+1);
+ left->ends(this);
+ right->ends(this);
+ left->scheduled();
+ return right;
+ }
+}
+
+/*! For all tree tests */
+template<typename NodeType>
+START_UTEST(TestTree)
+ Atomic value(0u);
+ std::cout << "nodeNum = " << (2 << maxLevel) - 1 << std::endl;
+ double t = getSeconds();
+ Task *done = PF_NEW(TaskDone);
+ Task *root = PF_NEW(NodeType, value, 0);
+ root->starts(done);
+ done->scheduled();
+ root->scheduled();
+ TaskingSystemEnter();
+ t = getSeconds() - t;
+ std::cout << t * 1000. << " ms" << std::endl;
+ FATAL_IF(value != (1 << maxLevel), "TestTree failed");
+END_UTEST(TestTree)
+
+///////////////////////////////////////////////////////////////////////////////
+// We try to stress the internal allocator here
+///////////////////////////////////////////////////////////////////////////////
+class TaskAllocate : public TaskSet {
+public:
+ TaskAllocate(size_t elemNum) : TaskSet(elemNum) {}
+ virtual void run(size_t elemID);
+ enum { allocNum = 1 << 10 };
+ enum { iterNum = 1 << 5 };
+};
+
+void TaskAllocate::run(size_t elemID) {
+ Task *tasks[allocNum];
+ for (int j = 0; j < iterNum; ++j) {
+ const int taskNum = rand() % allocNum;
+ for (int i = 0; i < taskNum; ++i) tasks[i] = PF_NEW(TaskDummy);
+ for (int i = 0; i < taskNum; ++i) PF_DELETE(tasks[i]);
+ }
+}
+
+START_UTEST(TestAllocator)
+ Task *done = PF_NEW(TaskDone);
+ Task *allocate = PF_NEW(TaskAllocate, 1 << 10);
+ double t = getSeconds();
+ allocate->starts(done);
+ done->scheduled();
+ allocate->scheduled();
+ TaskingSystemEnter();
+ t = getSeconds() - t;
+ std::cout << t * 1000. << " ms" << std::endl;
+END_UTEST(TestAllocator)
+
+///////////////////////////////////////////////////////////////////////////////
+// We are making the queue full to make the system recurse to empty it
+///////////////////////////////////////////////////////////////////////////////
+class TaskFull : public Task {
+public:
+ enum { taskToSpawn = 1u << 16u };
+ TaskFull(const char *name, Atomic &counter, int lvl = 0) :
+ Task(name), counter(counter), lvl(lvl) {}
+ virtual Task* run(void) {
+ if (lvl == 0)
+ for (size_t i = 0; i < taskToSpawn; ++i) {
+ Task *task = PF_NEW(TaskFull, "TaskFullLvl1", counter, 1);
+ task->ends(this);
+ task->scheduled();
+ }
+ else
+ counter++;
+ return NULL;
+ }
+ Atomic &counter;
+ int lvl;
+};
+
+START_UTEST(TestFullQueue)
+ Atomic counter(0u);
+ double t = getSeconds();
+ Task *done = PF_NEW(TaskDone);
+ for (size_t i = 0; i < 64; ++i) {
+ Task *task = PF_NEW(TaskFull, "TaskFull", counter);
+ task->starts(done);
+ task->scheduled();
+ }
+ done->scheduled();
+ TaskingSystemEnter();
+ t = getSeconds() - t;
+ std::cout << t * 1000. << " ms" << std::endl;
+ FATAL_IF (counter != 64 * TaskFull::taskToSpawn, "TestFullQueue failed");
+END_UTEST(TestFullQueue)
+
+///////////////////////////////////////////////////////////////////////////////
+// We spawn a lot of affinity jobs to saturate the affinity queues
+///////////////////////////////////////////////////////////////////////////////
+class TaskAffinity : public Task {
+public:
+ enum { taskToSpawn = 2048u };
+ TaskAffinity(Task *done, Atomic &counter, int lvl = 0) :
+ Task("TaskAffinity"), counter(counter), lvl(lvl) {}
+ virtual Task *run(void) {
+ if (lvl == 1)
+ counter++;
+ else {
+ const uint32 threadNum = TaskingSystemGetThreadNum();
+ for (uint32 i = 0; i < taskToSpawn; ++i) {
+ Task *task = PF_NEW(TaskAffinity, done.ptr, counter, 1);
+ task->setAffinity(i % threadNum);
+ task->ends(this);
+ task->scheduled();
+ }
+ }
+ return NULL;
+ }
+ Atomic &counter;
+ Ref<Task> done;
+ int lvl;
+};
+
+START_UTEST(TestAffinity)
+ enum { batchNum = 512 };
+ for (int i = 0; i < 8; ++i) {
+ Atomic counter(0u);
+ double t = getSeconds();
+ Ref<Task> done = PF_NEW(TaskDone);
+ for (size_t i = 0; i < batchNum; ++i) {
+ Task *task = PF_NEW(TaskAffinity, done.ptr, counter);
+ task->starts(done.ptr);
+ task->scheduled();
+ }
+ done->scheduled();
+ TaskingSystemEnter();
+ t = getSeconds() - t;
+ std::cout << t * 1000. << " ms" << std::endl;
+ std::cout << counter << std::endl;
+ FATAL_IF (counter != batchNum * TaskAffinity::taskToSpawn, "TestAffinity failed");
+ }
+END_UTEST(TestAffinity)
+
+///////////////////////////////////////////////////////////////////////////////
+// Exponential Fibonnaci to stress the task spawning and the completions
+///////////////////////////////////////////////////////////////////////////////
+static Atomic fiboNum(0u);
+class TaskFiboSpawn : public Task {
+public:
+ TaskFiboSpawn(uint64 rank, uint64 *root = NULL) :
+ Task("TaskFiboSpawn"), rank(rank), root(root) {fiboNum++;}
+ virtual Task* run(void);
+ uint64 rank, sumLeft, sumRight;
+ uint64 *root;
+};
+
+class FiboSumTask : public Task {
+public:
+ FiboSumTask(TaskFiboSpawn *fibo) : Task("FiboSumTask"), fibo(fibo) {}
+ virtual Task* run(void);
+ TaskFiboSpawn *fibo;
+};
+
+Task *TaskFiboSpawn::run(void) {
+ if (rank > 1) {
+ TaskFiboSpawn *left = PF_NEW(TaskFiboSpawn, rank-1, &this->sumLeft);
+ TaskFiboSpawn *right = PF_NEW(TaskFiboSpawn, rank-2, &this->sumRight);
+ FiboSumTask *sum = PF_NEW(FiboSumTask, this);
+ left->starts(sum);
+ right->starts(sum);
+ sum->ends(this);
+ sum->scheduled();
+ left->scheduled();
+ return right;
+ } else if (rank == 1) {
+ if (root) *root = 1;
+ return NULL;
+ } else {
+ if (root) *root = 0;
+ return NULL;
+ }
+}
+
+Task *FiboSumTask::run(void) {
+ assert(fibo);
+ if (fibo->root) *fibo->root = fibo->sumLeft + fibo->sumRight;
+ return NULL;
+}
+
+static uint64 fiboLinear(uint64 rank)
+{
+ uint64 rn0 = 0, rn1 = 1;
+ if (rank == 0) return rn0;
+ if (rank == 1) return rn1;
+ for (uint64 i = 2; i <= rank; ++i) {
+ uint64 sum = rn0 + rn1;
+ rn0 = rn1;
+ rn1 = sum;
+ }
+ return rn1;
+}
+
+START_UTEST(TestFibo)
+{
+ const uint64 rank = rand() % 32;
+ uint64 sum;
+ double t = getSeconds();
+ fiboNum = 0u;
+ Ref<TaskFiboSpawn> fibo = PF_NEW(TaskFiboSpawn, rank, &sum);
+ Task *done = PF_NEW(TaskDone);
+ fibo->starts(done);
+ fibo->scheduled();
+ done->scheduled();
+ TaskingSystemEnter();
+ t = getSeconds() - t;
+ std::cout << t * 1000. << " ms" << std::endl;
+ std::cout << "Fibonacci Task Num: "<< fiboNum << std::endl;
+ FATAL_IF (sum != fiboLinear(rank), "TestFibonacci failed");
+}
+END_UTEST(TestFibo)
+
+///////////////////////////////////////////////////////////////////////////////
+// Task with multiple dependencies
+///////////////////////////////////////////////////////////////////////////////
+class TaskMultiTrigger : public Task,
+ public MultiDependencyPolicy<TaskMultiTrigger>
+{
+public:
+ TaskMultiTrigger(int32 *valueToSet) : valueToSet(valueToSet) {}
+ virtual Task *run(void) { *valueToSet = 1; return NULL; }
+private:
+ int32 *valueToSet;
+};
+
+class TaskTriggered : public Task
+{
+public:
+ TaskTriggered(const int32 *valueToRead, Atomic32 &dst) :
+ valueToRead(valueToRead), dst(dst) {}
+ virtual Task *run(void) { dst += *valueToRead; return NULL; }
+private:
+ const int32 *valueToRead;
+ Atomic32 &dst;
+};
+
+START_UTEST(TestMultiDependency)
+{
+ static const uint32 multiTaskToSpawn = 512;
+ static const uint32 triggeredTaskToSpawn = 512;
+ static const uint32 valueToSetNum = multiTaskToSpawn;
+
+ int32 *toSet = PF_NEW_ARRAY(int32, valueToSetNum);
+ Atomic32 dst(0);
+ Task *doneTask = PF_NEW(TaskDone);
+ for (uint32 i = 0; i < valueToSetNum; ++i) toSet[i] = 0;
+ for (uint32 i = 0; i < multiTaskToSpawn; ++i) {
+ Ref<TaskMultiTrigger> task = PF_NEW(TaskMultiTrigger, toSet + i);
+ for (uint32 j = 0; j < triggeredTaskToSpawn; ++j) {
+ Ref<Task> triggered = PF_NEW(TaskTriggered, toSet + i, dst);
+ Ref<Task> dummy = PF_NEW(TaskDummy);
+ task->multiStarts(dummy);
+ dummy->starts(triggered);
+ triggered->starts(doneTask);
+ triggered->scheduled();
+ dummy->scheduled();
+ }
+ task->scheduled();
+ }
+ doneTask->scheduled();
+ TaskingSystemEnter();
+ PF_DELETE_ARRAY(toSet);
+ const uint32 result = dst;
+ std::cout << "result: " << result << std::endl;
+ FATAL_IF(result != multiTaskToSpawn * triggeredTaskToSpawn,
+ "MultiDependency failed");
+}
+END_UTEST(TestMultiDependency)
+
+START_UTEST(TestMultiDependencyTwoStage)
+{
+ static const uint32 multiTaskToSpawn = 512;
+ static const uint32 triggeredTaskToSpawn = 512;
+ static const uint32 valueToSetNum = multiTaskToSpawn;
+
+ int32 *toSet = PF_NEW_ARRAY(int32, valueToSetNum);
+ Atomic32 dst(0);
+ Task *doneTask = PF_NEW(TaskDone);
+ for (uint32 i = 0; i < valueToSetNum; ++i) toSet[i] = 0;
+ for (uint32 i = 0; i < multiTaskToSpawn; ++i) {
+ Ref<TaskMultiTrigger> task = PF_NEW(TaskMultiTrigger, toSet + i);
+ for (uint32 j = 0; j < triggeredTaskToSpawn; ++j) {
+ Ref<Task> triggered = PF_NEW(TaskTriggered, toSet + i, dst);
+ task->multiStarts(triggered);
+ triggered->starts(doneTask);
+ triggered->scheduled();
+ }
+ task->scheduled();
+ }
+ doneTask->scheduled();
+ TaskingSystemEnter();
+ PF_DELETE_ARRAY(toSet);
+ const uint32 result = dst;
+ std::cout << "result: " << result << std::endl;
+ FATAL_IF(result != multiTaskToSpawn * triggeredTaskToSpawn,
+ "MultiDependency failed");
+}
+END_UTEST(TestMultiDependencyTwoStage)
+
+START_UTEST(TestMultiDependencyRandomStart)
+{
+ static const uint32 multiTaskToSpawn = 512;
+ static const uint32 triggeredTaskToSpawn = 512;
+ static const uint32 valueToSetNum = multiTaskToSpawn;
+ static const uint32 repeatNum = 8;
+ Random rand;
+ for (uint32 i = 0; i < repeatNum; ++i) {
+ int32 *toSet = PF_NEW_ARRAY(int32, valueToSetNum);
+ Atomic32 dst(0);
+ Ref<Task> doneTask = PF_NEW(TaskDone);
+ for (uint32 i = 0; i < valueToSetNum; ++i) toSet[i] = 0;
+ for (uint32 i = 0; i < multiTaskToSpawn; ++i) {
+ Ref<TaskMultiTrigger> task = PF_NEW(TaskMultiTrigger, toSet + i);
+ bool isScheduled = false;
+ for (uint32 j = 0; j < triggeredTaskToSpawn; ++j) {
+ Ref<Task> triggered = PF_NEW(TaskTriggered, toSet + i, dst);
+ task->multiStarts(triggered);
+ triggered->starts(doneTask);
+ triggered->scheduled();
+ if (rand.getFloat() < 0.8 && isScheduled == false) {
+ task->scheduled();
+ isScheduled = true;
+ }
+ }
+ if (isScheduled == false) task->scheduled();
+ }
+ doneTask->scheduled();
+ TaskingSystemEnter();
+ PF_DELETE_ARRAY(toSet);
+ const uint32 result = dst;
+ std::cout << "result: " << result << std::endl;
+ FATAL_IF(result != multiTaskToSpawn * triggeredTaskToSpawn,
+ "MultiDependencyRandomStart failed");
+ }
+}
+END_UTEST(TestMultiDependencyRandomStart)
+
+///////////////////////////////////////////////////////////////////////////////
+// Test tasking lock and unlock
+///////////////////////////////////////////////////////////////////////////////
+class TaskLockUnlock : public Task
+{
+public:
+ TaskLockUnlock(int32 *shared) : shared(shared) {}
+ virtual Task *run(void) {
+ TaskingSystemLock();
+ *shared = *shared + 1;
+ TaskingSystemUnlock();
+ return NULL;
+ }
+ int32 *shared;
+};
+
+START_UTEST(TestLockUnlock)
+{
+ static const uint32 taskNum = 1024;
+ int32 shared = 0;
+ Ref<Task> doneTask = PF_NEW(TaskDone);
+ for (uint32 i = 0; i < taskNum; ++i) {
+ Task *updateTask = PF_NEW(TaskLockUnlock, &shared);
+ updateTask->starts(doneTask);
+ updateTask->scheduled();
+ }
+ doneTask->scheduled();
+ TaskingSystemEnter();
+ FATAL_IF(shared != int32(taskNum), "TestLockUnlock failed");
+}
+END_UTEST(TestLockUnlock)
+
+///////////////////////////////////////////////////////////////////////////////
+// Test tasking profiler
+///////////////////////////////////////////////////////////////////////////////
+#if PF_TASK_PROFILER
+class UTestProfiler : public TaskProfiler
+{
+public:
+ UTestProfiler(void) :
+ sleepNum(0), wakeUpNum(0),
+ lockNum(0), unlockNum(0),
+ runStartNum(0), runEndNum(0), endNum(0) {}
+ virtual void onSleep(uint32 threadID) {sleepNum++;}
+ virtual void onWakeUp(uint32 threadID) {wakeUpNum++;}
+ virtual void onLock(uint32 threadID) {lockNum++;}
+ virtual void onUnlock(uint32 threadID) {unlockNum++;}
+ virtual void onRunStart(const char *taskName, uint32 threadID) {runStartNum++;}
+ virtual void onRunEnd(const char *taskName, uint32 threadID) {runEndNum++;}
+ virtual void onEnd(const char *taskName, uint32 threadID) {endNum++;}
+ Atomic sleepNum;
+ Atomic wakeUpNum;
+ Atomic lockNum;
+ Atomic unlockNum;
+ Atomic runStartNum;
+ Atomic runEndNum;
+ Atomic endNum;
+};
+
+START_UTEST(TestProfiler)
+{
+ UTestProfiler *profiler = PF_NEW(UTestProfiler);
+ TaskingSystemSetProfiler(profiler);
+ TestFibo();
+ TestTaskSet();
+ TestMultiDependency();
+ TestLockUnlock();
+#define OUTPUT_FIELD(FIELD) \
+ std::cout << #FIELD ": " << profiler->FIELD << std::endl
+ OUTPUT_FIELD(sleepNum);
+ OUTPUT_FIELD(wakeUpNum);
+ OUTPUT_FIELD(lockNum);
+ OUTPUT_FIELD(unlockNum);
+ OUTPUT_FIELD(runStartNum);
+ OUTPUT_FIELD(runEndNum);
+ OUTPUT_FIELD(endNum);
+#undef OUTPUT_FIELD
+ TaskingSystemSetProfiler(NULL);
+ PF_DELETE(profiler);
+}
+END_UTEST(TestProfiler)
+#endif /* PF_TASK_PROFILER */
+
+/*! Run all tasking tests */
+void utest_tasking(void)
+{
+ TestDummy();
+ TestTree<TaskNodeOpt>();
+ TestTree<TaskNode>();
+ TestTree<TaskCascadeNodeOpt>();
+ TestTree<TaskCascadeNode>();
+ TestTaskSet();
+ TestAllocator();
+ TestFullQueue();
+ TestAffinity();
+ TestFibo();
+ TestMultiDependency();
+ TestMultiDependencyTwoStage();
+ TestMultiDependencyRandomStart();
+ TestLockUnlock();
+ TestProfiler();
+}
+
+UTEST_REGISTER(utest_tasking);