[
  {
    "path": ".gitignore",
    "content": "*.o\n*.gch\ndns2tcp\n.vscode/\n"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU AFFERO GENERAL PUBLIC LICENSE\n                       Version 3, 19 November 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU Affero General Public License is a free, copyleft license for\nsoftware and other kinds of works, specifically designed to ensure\ncooperation with the community in the case of network server software.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nour General Public Licenses are intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  Developers that use our General Public Licenses protect your rights\nwith two steps: (1) assert copyright on the software, and (2) offer\nyou this License which gives you legal permission to copy, distribute\nand/or modify the software.\n\n  A secondary benefit of defending all users' freedom is that\nimprovements made in alternate versions of the program, if they\nreceive widespread use, become available for other developers to\nincorporate.  Many developers of free software are heartened and\nencouraged by the resulting cooperation.  However, in the case of\nsoftware used on network servers, this result may fail to come about.\nThe GNU General Public License permits making a modified version and\nletting the public access it on a server without ever releasing its\nsource code to the public.\n\n  The GNU Affero General Public License is designed specifically to\nensure that, in such cases, the modified source code becomes available\nto the community.  It requires the operator of a network server to\nprovide the source code of the modified version running there to the\nusers of that server.  Therefore, public use of a modified version, on\na publicly accessible server, gives the public access to the source\ncode of the modified version.\n\n  An older license, called the Affero General Public License and\npublished by Affero, was designed to accomplish similar goals.  This is\na different license, not a version of the Affero GPL, but Affero has\nreleased a new version of the Affero GPL which permits relicensing under\nthis license.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU Affero General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Remote Network Interaction; Use with the GNU General Public License.\n\n  Notwithstanding any other provision of this License, if you modify the\nProgram, your modified version must prominently offer all users\ninteracting with it remotely through a computer network (if your version\nsupports such interaction) an opportunity to receive the Corresponding\nSource of your version by providing access to the Corresponding Source\nfrom a network server at no charge, through some standard or customary\nmeans of facilitating copying of software.  This Corresponding Source\nshall include the Corresponding Source for any work covered by version 3\nof the GNU General Public License that is incorporated pursuant to the\nfollowing paragraph.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the work with which it is combined will remain governed by version\n3 of the GNU General Public License.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU Affero General Public License from time to time.  Such new versions\nwill be similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU Affero General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU Affero General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU Affero General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Affero General Public License as published\n    by the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Affero General Public License for more details.\n\n    You should have received a copy of the GNU Affero General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If your software can interact with users remotely through a computer\nnetwork, you should also make sure that it provides a way for users to\nget its source.  For example, if your program is a web application, its\ninterface could display a \"Source\" link that leads users to an archive\nof the code.  There are many ways you could offer source, and different\nsolutions will be better for different programs; see section 13 for the\nspecific requirements.\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU AGPL, see\n<https://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "Makefile",
    "content": "CC = gcc\nCFLAGS = -std=c99 -Wall -Wextra -Wvla -O3 -flto -fno-strict-aliasing -ffunction-sections -fdata-sections -DNDEBUG\nLDFLAGS = -O3 -flto -fno-strict-aliasing -Wl,--gc-sections -s\nLIBS = -lm\nSRCS = dns2tcp.c libev/ev.c\nOBJS = $(SRCS:.c=.o)\nMAIN = dns2tcp\nDESTDIR = /usr/local/bin\n\n.PHONY: all install clean\n\nall: $(MAIN)\n\ninstall: $(MAIN)\n\tmkdir -p $(DESTDIR)\n\tinstall -m 0755 $(MAIN) $(DESTDIR)\n\nclean:\n\t$(RM) $(MAIN) *.o libev/*.o\n\n$(MAIN): $(OBJS)\n\t$(CC) $(LDFLAGS) -o $(MAIN) $(OBJS) $(LIBS)\n\n.c.o:\n\t$(CC) $(CFLAGS) -c $< -o $@\n"
  },
  {
    "path": "README.md",
    "content": "# dns2tcp\n\n一个 DNS 实用工具，用于将 DNS 查询从 UDP 转为 TCP。\n\n当然有很多 DNS 工具都可以实现这个功能，比如 pdnsd、dnsforwarder；但如果你只是想使用其 UDP 转 TCP 功能（比如配合 dnsmasq，将 dnsmasq 向上游发出的 DNS 查询从 UDP 转为 TCP），那么 dns2tcp 可能是更好的选择。\n\n`dns2tcp` 设计的非常简洁以及易用，它不需要任何配置文件，在命令行参数中指定一个 **本地 UDP 监听地址** 以及一个 **远程 DNS 服务器地址**（该 DNS 服务器支持 TCP 查询）即可，没有任何多余功能。\n\n## 如何编译\n\n> 为了方便使用，[releases](https://github.com/zfl9/dns2tcp/releases) 页面发布了 linux 下常见架构的 musl 静态链接二进制。\n\n```bash\ngit clone https://github.com/zfl9/dns2tcp\ncd dns2tcp\nmake && sudo make install\n```\n\ndns2tcp 默认安装到 `/usr/local/bin/dns2tcp`，可安装到其它目录，如 `make install DESTDIR=/opt/local/bin`。\n\n交叉编译时只需指定 CC 变量，如 `make CC=aarch64-linux-gnu-gcc`（若报错，请先执行 `make clean`，然后再试）。\n\n## 如何运行\n\n```bash\n# sh/bash 可以不加引号，zsh 必须加引号，防止#被转义\n# UPDATE: 从 v1.1.1 版本开始可以省略端口号，默认是 53\ndns2tcp -L \"127.0.0.1#5353\" -R \"8.8.8.8#53\"\n\n# 如果想在后台运行，可以这样做：\n(dns2tcp -L \"127.0.0.1#5353\" -R \"8.8.8.8#53\" </dev/null &>>/var/log/dns2tcp.log &)\n```\n\n- `-L` 选项指定本地监听地址，该监听地址接受 UDP 协议的 DNS 查询。\n- `-R` 选项指定远程 DNS 服务器地址，该 DNS 服务器应支持 TCP 查询。\n\n## 小技巧\n\n借助 iptables，将本机发往 8.8.8.8:53 的 UDP 查询请求，强行重定向至本机 dns2tcp 监听端口，这样就可以不用修改原有 dns 组件的配置，无感转换为 TCP 查询。还是上面那个例子，在启动 dns2tcp 之后，再执行如下 iptables 命令：\n\n```bash\n# 将目标地址为 8.8.8.8:53/udp 的包重定向至 dns2tcp 监听端口，实现透明 udp2tcp 转换\niptables -t nat -A OUTPUT -p udp -d 8.8.8.8 --dport 53 -j REDIRECT --to-ports 5353\n```\n\n你可以在本机使用 `dig @8.8.8.8 baidu.com` 测试，观察 dns2tcp 日志（带上 -v），就会发现走 TCP 出去了。\n\n## 全部参数\n\n```console\nusage: dns2tcp <-L listen> <-R remote> [options...]\n -L <ip[#port]>          udp listen address, port default to 53\n -R <ip[#port]>          tcp remote address, port default to 53\n -l <ip[#port]>          tcp local address, port default to 0\n -s <syncnt>             set TCP_SYNCNT option for tcp socket\n -6                      set IPV6_V6ONLY option for udp socket\n -r                      set SO_REUSEPORT option for udp socket\n -v                      print verbose log, used for debugging\n -V                      print version number of dns2tcp and exit\n -h                      print help information of dns2tcp and exit\nbug report: https://github.com/zfl9/dns2tcp. email: zfl9.com@gmail.com\n```\n\n`-l`：设置`TCP`连接的本地地址（源地址），`0地址`或`0端口`表示由系统选择。\n\n`-s`：对`TCP`套接字设置`TCP_SYNCNT`，该选项值将影响`TCP`的连接超时时间。\n\n`-6`：对`UDP`套接字设置`IPV6_V6ONLY`，建议始终启用，把 v4 和 v6 监听严格区分开。\n\n`-r`：对`UDP`套接字设置`SO_REUSEPORT`，用于多进程负载均衡，Linux 3.9+ 开始可用。\n"
  },
  {
    "path": "dns2tcp.c",
    "content": "#define _GNU_SOURCE\n#include <stdio.h>\n#include <stdlib.h>\n#include <stddef.h>\n#include <stdint.h>\n#include <stdbool.h>\n#include <string.h>\n#include <time.h>\n#include <errno.h>\n#include <signal.h>\n#include <unistd.h>\n#include <arpa/inet.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <netinet/tcp.h>\n#include \"libev/ev.h\"\n\n#define DNS2TCP_VER \"dns2tcp v1.1.2\"\n\n#ifndef IPV6_V6ONLY\n  #define IPV6_V6ONLY 26\n#endif\n\n#ifndef SO_REUSEPORT\n  #define SO_REUSEPORT 15\n#endif\n\n#ifndef TCP_SYNCNT\n  #define TCP_SYNCNT 7\n#endif\n\n#define IP4STRLEN INET_ADDRSTRLEN /* include \\0 */\n#define IP6STRLEN INET6_ADDRSTRLEN /* include \\0 */\n#define PORTSTRLEN 6 /* \"65535\" (include \\0) */\n\n#define DNS_MSGSZ 1472 /* mtu:1500 - iphdr:20 - udphdr:8 */\n\n/* ======================== helper ======================== */\n\n#define __unused __attribute__((unused))\n\n#define alignto(alignment) __attribute__((aligned(alignment)))\n\n// get the struct pointer by the field(member) pointer\n#define container_of(p_field, struct_type, field_name) ( \\\n    (struct_type *) ((void *)(p_field) - offsetof(struct_type, field_name)) \\\n)\n\n/* ======================== log-func ======================== */\n\n#define log_write(color, level, fmt, args...) ({ \\\n    time_t t_ = time(NULL); \\\n    const struct tm *tm_ = localtime(&t_); \\\n    printf(\"\\e[\" color \";1m%d-%02d-%02d %02d:%02d:%02d \" level \"\\e[0m \" \\\n        \"\\e[1m[%s]\\e[0m \" fmt \"\\n\", \\\n        tm_->tm_year + 1900, tm_->tm_mon + 1, tm_->tm_mday, \\\n        tm_->tm_hour,        tm_->tm_min,     tm_->tm_sec, \\\n        __func__, ##args); \\\n})\n\n#define log_verbose(fmt, args...) ({ \\\n    if (verbose) log_info(fmt, ##args); \\\n})\n\n#define log_info(fmt, args...) \\\n    log_write(\"32\", \"I\", fmt, ##args)\n\n#define log_warning(fmt, args...) \\\n    log_write(\"33\", \"W\", fmt, ##args)\n\n#define log_error(fmt, args...) \\\n    log_write(\"35\", \"E\", fmt, ##args)\n\n/* ======================== socket-addr ======================== */\n\nunion skaddr {\n    struct sockaddr sa;\n    struct sockaddr_in sin;\n    struct sockaddr_in6 sin6;\n};\n\n#define skaddr_family(addr) ((addr)->sa.sa_family)\n#define skaddr_is_sin(addr) (skaddr_family(addr) == AF_INET)\n#define skaddr_is_sin6(addr) (skaddr_family(addr) == AF_INET6)\n#define skaddr_len(addr) (skaddr_is_sin(addr) ? sizeof((addr)->sin) : sizeof((addr)->sin6))\n\nstatic void skaddr_from_text(union skaddr *addr, int family, const char *ipstr, uint16_t port) {\n    if (family == AF_INET) {\n        addr->sin.sin_family = AF_INET;\n        inet_pton(AF_INET, ipstr, &addr->sin.sin_addr);\n        addr->sin.sin_port = htons(port);\n    } else {\n        addr->sin6.sin6_family = AF_INET6;\n        inet_pton(AF_INET6, ipstr, &addr->sin6.sin6_addr);\n        addr->sin6.sin6_port = htons(port);\n    }\n}\n\nstatic void skaddr_to_text(const union skaddr *addr, char *ipstr, uint16_t *port) {\n    if (skaddr_is_sin(addr)) {\n        inet_ntop(AF_INET, &addr->sin.sin_addr, ipstr, IP4STRLEN);\n        *port = ntohs(addr->sin.sin_port);\n    } else {\n        inet_ntop(AF_INET6, &addr->sin6.sin6_addr, ipstr, IP6STRLEN);\n        *port = ntohs(addr->sin6.sin6_port);\n    }\n}\n\n/* AF_INET, AF_INET6, -1(invalid) */\nstatic int get_ipstr_family(const char *ipstr) {\n    char tmp[16];\n    if (!ipstr)\n        return -1;\n    if (inet_pton(AF_INET, ipstr, &tmp) == 1)\n        return AF_INET;\n    if (inet_pton(AF_INET6, ipstr, &tmp) == 1)\n        return AF_INET6;\n    return -1;\n}\n\n/* ======================== context ======================== */\n\ntypedef struct {\n    evio_t       watcher; /* tcp watcher */\n    char         buffer[2 + DNS_MSGSZ] alignto(__alignof__(uint16_t)); /* msglen(be16) + msg */\n    uint16_t     nbytes; /* nrecv or nsend */\n    union skaddr srcaddr;\n} ctx_t;\n\n/* ======================== global-vars ======================== */\n\nenum {\n    FLAG_IPV6_V6ONLY = 1 << 0, /* udp listen */\n    FLAG_REUSE_PORT  = 1 << 1, /* udp listen */\n    FLAG_VERBOSE     = 1 << 2, /* logging */\n    FLAG_LOCAL_ADDR  = 1 << 3, /* tcp local addr */\n};\n\n#define has_flag(flag) (g_flags & (flag))\n#define add_flag(flag) (g_flags |= (flag))\n\n#define verbose has_flag(FLAG_VERBOSE)\n\nstatic uint8_t g_flags = 0;\nstatic uint8_t g_syn_cnt = 0;\n\n/* udp listen */\nstatic int          g_listen_fd               = -1;\nstatic char         g_listen_ipstr[IP6STRLEN] = {0};\nstatic uint16_t     g_listen_port             = 0;\nstatic union skaddr g_listen_skaddr           = {0};\n\n/* tcp server address */\nstatic char         g_remote_ipstr[IP6STRLEN] = {0};\nstatic uint16_t     g_remote_port             = 0;\nstatic union skaddr g_remote_skaddr           = {0};\n\n/* tcp local address [optional] */\nstatic char         g_local_ipstr[IP6STRLEN] = {0};\nstatic uint16_t     g_local_port             = 0;\nstatic union skaddr g_local_skaddr           = {0};\n\nstatic void udp_recvmsg_cb(evloop_t *evloop, evio_t *watcher, int events);\nstatic void tcp_connect_cb(evloop_t *evloop, evio_t *watcher, int events);\nstatic void tcp_sendmsg_cb(evloop_t *evloop, evio_t *watcher, int events);\nstatic void tcp_recvmsg_cb(evloop_t *evloop, evio_t *watcher, int events);\n\nstatic void print_help(void) {\n    printf(\"usage: dns2tcp <-L listen> <-R remote> [options...]\\n\"\n           \" -L <ip[#port]>          udp listen address, port default to 53\\n\"\n           \" -R <ip[#port]>          tcp remote address, port default to 53\\n\"\n           \" -l <ip[#port]>          tcp local address, port default to 0\\n\"\n           \" -s <syncnt>             set TCP_SYNCNT option for tcp socket\\n\"\n           \" -6                      set IPV6_V6ONLY option for udp socket\\n\"\n           \" -r                      set SO_REUSEPORT option for udp socket\\n\"\n           \" -v                      print verbose log, used for debugging\\n\"\n           \" -V                      print version number of dns2tcp and exit\\n\"\n           \" -h                      print help information of dns2tcp and exit\\n\"\n           \"bug report: https://github.com/zfl9/dns2tcp. email: zfl9.com@gmail.com\\n\"\n    );\n}\n\nenum addr_type {\n    ADDR_UDP_LISTEN,\n    ADDR_TCP_REMOTE,\n    ADDR_TCP_LOCAL,\n};\n\nstatic void parse_addr(const char *addr, enum addr_type addr_type) {\n    const char *end = addr + strlen(addr);\n    const char *sep = strchr(addr, '#') ?: end;\n\n    const char *ipstart = addr;\n    int iplen = sep - ipstart;\n\n    const char *portstart = sep + 1;\n    int portlen = (sep < end) ? end - portstart : -1;\n\n    char ipstr[IP6STRLEN];\n    if (iplen >= IP6STRLEN) goto err;\n\n    memcpy(ipstr, ipstart, iplen);\n    ipstr[iplen] = 0;\n\n    int family = get_ipstr_family(ipstr);\n    if (family == -1) goto err;\n\n    uint16_t port = addr_type != ADDR_TCP_LOCAL ? 53 : 0;\n    if (portlen >= 0 && (port = strtoul(portstart, NULL, 10)) == 0 && addr_type != ADDR_TCP_LOCAL) goto err;\n\n    #define set_addr(tag) ({ \\\n        strcpy(g_##tag##_ipstr, ipstr); \\\n        g_##tag##_port = port; \\\n        skaddr_from_text(&g_##tag##_skaddr, family, ipstr, port); \\\n    })\n\n    switch (addr_type) {\n        case ADDR_UDP_LISTEN:\n            set_addr(listen);\n            break;\n        case ADDR_TCP_REMOTE:\n            set_addr(remote);\n            break;\n        case ADDR_TCP_LOCAL:\n            set_addr(local);\n            break;\n    }\n\n    #undef set_addr\n\n    return;\n\nerr:;\n    const char *type;\n    switch (addr_type) {\n        case ADDR_UDP_LISTEN:\n            type = \"udp_listen\";\n            break;\n        case ADDR_TCP_REMOTE:\n            type = \"tcp_remote\";\n            break;\n        case ADDR_TCP_LOCAL:\n            type = \"tcp_local\";\n            break;\n    }\n\n    printf(\"invalid %s address: '%s'\\n\", type, addr);\n    print_help();\n    exit(1);\n}\n\nstatic void parse_opt(int argc, char *argv[]) {\n    char opt_listen_addr[IP6STRLEN + PORTSTRLEN] = {0};\n    char opt_remote_addr[IP6STRLEN + PORTSTRLEN] = {0};\n    char opt_local_addr[IP6STRLEN + PORTSTRLEN] = {0};\n\n    opterr = 0;\n    int shortopt;\n    const char *optstr = \"L:R:l:s:6rafvVh\";\n    while ((shortopt = getopt(argc, argv, optstr)) != -1) {\n        switch (shortopt) {\n            case 'L':\n                if (strlen(optarg) + 1 > IP6STRLEN + PORTSTRLEN) {\n                    printf(\"invalid udp listen addr: %s\\n\", optarg);\n                    goto err;\n                }\n                strcpy(opt_listen_addr, optarg);\n                break;\n            case 'R':\n                if (strlen(optarg) + 1 > IP6STRLEN + PORTSTRLEN) {\n                    printf(\"invalid tcp remote addr: %s\\n\", optarg);\n                    goto err;\n                }\n                strcpy(opt_remote_addr, optarg);\n                break;\n            case 'l':\n                if (strlen(optarg) + 1 > IP6STRLEN + PORTSTRLEN) {\n                    printf(\"invalid tcp local addr: %s\\n\", optarg);\n                    goto err;\n                }\n                strcpy(opt_local_addr, optarg);\n                add_flag(FLAG_LOCAL_ADDR);\n                break;\n            case 's':\n                g_syn_cnt = strtoul(optarg, NULL, 10);\n                if (g_syn_cnt == 0) {\n                    printf(\"invalid tcp syn cnt: %s\\n\", optarg);\n                    goto err;\n                }\n                break;\n            case '6':\n                add_flag(FLAG_IPV6_V6ONLY);\n                break;\n            case 'r':\n                add_flag(FLAG_REUSE_PORT);\n                break;\n            case 'a':\n                /* nop */\n                break;\n            case 'f':\n                /* nop */\n                break;\n            case 'v':\n                add_flag(FLAG_VERBOSE);\n                break;\n            case 'V':\n                printf(DNS2TCP_VER\"\\n\");\n                exit(0);\n            case 'h':\n                print_help();\n                exit(0);\n            case '?':\n                if (!strchr(optstr, optopt)) {\n                    printf(\"unknown option '-%c'\\n\", optopt);\n                } else {\n                    printf(\"missing optval '-%c'\\n\", optopt);\n                }\n                goto err;\n        }\n    }\n\n    /* check the required opt */\n    if (strlen(opt_listen_addr) == 0) {\n        printf(\"missing option: '-L'\\n\");\n        goto err;\n    }\n    if (strlen(opt_remote_addr) == 0) {\n        printf(\"missing option: '-R'\\n\");\n        goto err;\n    }\n\n    parse_addr(opt_listen_addr, ADDR_UDP_LISTEN);\n    parse_addr(opt_remote_addr, ADDR_TCP_REMOTE);\n\n    if (has_flag(FLAG_LOCAL_ADDR))\n        parse_addr(opt_local_addr, ADDR_TCP_LOCAL);\n\n    return;\n\nerr:\n    print_help();\n    exit(1);\n}\n\n/* udp listen or tcp connect */\nstatic int create_socket(int family, int type) {\n    const char *err_op = NULL;\n\n    int fd = socket(family, type | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);\n    if (fd < 0) {\n        err_op = \"create_socket\";\n        goto out;\n    }\n\n    const int opt = 1;\n    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {\n        err_op = \"set_reuseaddr\";\n        goto out;\n    }\n\n    if (type == SOCK_DGRAM) {\n        // udp listen socket\n        if (has_flag(FLAG_REUSE_PORT) && setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)) < 0) {\n            err_op = \"set_reuseport\";\n            goto out;\n        }\n        if (family == AF_INET6 && has_flag(FLAG_IPV6_V6ONLY) && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) < 0) {\n            err_op = \"set_ipv6only\";\n            goto out;\n        }\n    } else {\n        // tcp connect socket\n        if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)) < 0) {\n            err_op = \"set_tcp_nodelay\";\n            goto out;\n        }\n        const int syn_cnt = g_syn_cnt;\n        if (syn_cnt && setsockopt(fd, IPPROTO_TCP, TCP_SYNCNT, &syn_cnt, sizeof(syn_cnt)) < 0) {\n            err_op = \"set_tcp_syncnt\";\n            goto out;\n        }\n    }\n\nout:\n    if (err_op)\n        log_error(\"%s(fd:%d, family:%d, type:%d) failed: %m\", err_op, fd, family, type);\n    return fd;\n}\n\nint main(int argc, char *argv[]) {\n    signal(SIGPIPE, SIG_IGN);\n    setvbuf(stdout, NULL, _IOLBF, 256);\n    parse_opt(argc, argv);\n\n    log_info(\"udp listen addr: %s#%hu\", g_listen_ipstr, g_listen_port);\n    log_info(\"tcp remote addr: %s#%hu\", g_remote_ipstr, g_remote_port);\n    if (has_flag(FLAG_LOCAL_ADDR)) log_info(\"tcp local addr: %s#%hu\", g_local_ipstr, g_local_port);\n    if (g_syn_cnt) log_info(\"enable TCP_SYNCNT:%hhu sockopt\", g_syn_cnt);\n    if (has_flag(FLAG_IPV6_V6ONLY)) log_info(\"enable IPV6_V6ONLY sockopt\");\n    if (has_flag(FLAG_REUSE_PORT)) log_info(\"enable SO_REUSEPORT sockopt\");\n    log_verbose(\"print the verbose log\");\n\n    g_listen_fd = create_socket(skaddr_family(&g_listen_skaddr), SOCK_DGRAM);\n    if (g_listen_fd < 0)\n        return 1;\n\n    if (bind(g_listen_fd, &g_listen_skaddr.sa, skaddr_len(&g_listen_skaddr)) < 0) {\n        log_error(\"bind udp address: %m\");\n        return 1;\n    }\n\n    evloop_t *evloop = ev_default_loop(0);\n\n    evio_t watcher;\n    ev_io_init(&watcher, udp_recvmsg_cb, g_listen_fd, EV_READ);\n    ev_io_start(evloop, &watcher);\n\n    return ev_run(evloop, 0);\n}\n\nstatic void udp_recvmsg_cb(evloop_t *evloop, evio_t *watcher __unused, int events __unused) {\n    ctx_t *ctx = malloc(sizeof(*ctx));\n\n    ssize_t nrecv = recvfrom(g_listen_fd, (void *)ctx->buffer + 2, DNS_MSGSZ, 0, &ctx->srcaddr.sa, &(socklen_t){sizeof(ctx->srcaddr)});\n    if (nrecv < 0) {\n        if (errno != EAGAIN && errno != EWOULDBLOCK)\n            log_warning(\"recv from udp socket: %m\");\n        goto free_ctx;\n    }\n\n    if (verbose) {\n        char ip[IP6STRLEN];\n        uint16_t port;\n        skaddr_to_text(&ctx->srcaddr, ip, &port);\n        log_info(\"recv from %s#%hu, nrecv:%zd\", ip, port, nrecv);\n    }\n\n    uint16_t *p_msglen = (void *)ctx->buffer;\n    *p_msglen = htons(nrecv); /* msg length */\n\n    int fd = create_socket(skaddr_family(&g_remote_skaddr), SOCK_STREAM);\n    if (fd < 0)\n        goto free_ctx;\n\n    if (has_flag(FLAG_LOCAL_ADDR) && bind(fd, &g_local_skaddr.sa, skaddr_len(&g_local_skaddr)) < 0) {\n        log_warning(\"bind tcp address: %m\");\n        goto close_fd;\n    }\n\n    if (connect(fd, &g_remote_skaddr.sa, skaddr_len(&g_remote_skaddr)) < 0 && errno != EINPROGRESS) {\n        log_warning(\"connect to %s#%hu: %m\", g_remote_ipstr, g_remote_port);\n        goto close_fd;\n    }\n    log_verbose(\"try to connect to %s#%hu\", g_remote_ipstr, g_remote_port);\n\n    ev_io_init(&ctx->watcher, tcp_connect_cb, fd, EV_WRITE);\n    ev_io_start(evloop, &ctx->watcher);\n\n    return;\n\nclose_fd:\n    close(fd);\nfree_ctx:\n    free(ctx);\n}\n\nstatic void free_ctx(ctx_t *ctx, evloop_t *evloop) {\n    ev_io_stop(evloop, &ctx->watcher);\n    close(ctx->watcher.fd);\n    free(ctx);\n}\n\nstatic void tcp_connect_cb(evloop_t *evloop, evio_t *watcher, int events __unused) {\n    ctx_t *ctx = container_of(watcher, ctx_t, watcher);\n\n    if (getsockopt(watcher->fd, SOL_SOCKET, SO_ERROR, &errno, &(socklen_t){sizeof(errno)}) < 0 || errno) {\n        log_warning(\"connect to %s#%hu: %m\", g_remote_ipstr, g_remote_port);\n        free_ctx(ctx, evloop);\n        return;\n    }\n    log_verbose(\"connect to %s#%hu succeed\", g_remote_ipstr, g_remote_port);\n\n    ctx->nbytes = 0;\n    ev_set_cb(watcher, tcp_sendmsg_cb);\n    ev_invoke(evloop, watcher, EV_WRITE);\n}\n\nstatic void tcp_sendmsg_cb(evloop_t *evloop, evio_t *watcher, int events __unused) {\n    ctx_t *ctx = container_of(watcher, ctx_t, watcher);\n\n    uint16_t *p_msglen = (void *)ctx->buffer;\n    uint16_t datalen = 2 + ntohs(*p_msglen);\n\n    ssize_t nsend = send(watcher->fd, (void *)ctx->buffer + ctx->nbytes, datalen - ctx->nbytes, 0);\n    if (nsend < 0) {\n        if (errno == EAGAIN || errno == EWOULDBLOCK) return;\n        log_warning(\"send to %s#%hu: %m\", g_remote_ipstr, g_remote_port);\n        free_ctx(ctx, evloop);\n        return;\n    }\n    log_verbose(\"send to %s#%hu, nsend:%zd\", g_remote_ipstr, g_remote_port, nsend);\n\n    ctx->nbytes += nsend;\n    if (ctx->nbytes >= datalen) {\n        ctx->nbytes = 0;\n        ev_io_stop(evloop, watcher);\n        ev_io_init(watcher, tcp_recvmsg_cb, watcher->fd, EV_READ);\n        ev_io_start(evloop, watcher);\n    }\n}\n\nstatic void tcp_recvmsg_cb(evloop_t *evloop, evio_t *watcher, int events __unused) {\n    ctx_t *ctx = container_of(watcher, ctx_t, watcher);\n\n    void *buffer = ctx->buffer;\n\n    ssize_t nrecv = recv(watcher->fd, buffer + ctx->nbytes, 2 + DNS_MSGSZ - ctx->nbytes, 0);\n    if (nrecv < 0) {\n        if (errno == EAGAIN || errno == EWOULDBLOCK) return;\n        log_warning(\"recv from %s#%hu: %m\", g_remote_ipstr, g_remote_port);\n        goto free_ctx;\n    }\n    if (nrecv == 0) {\n        log_warning(\"recv from %s#%hu: connection is closed\", g_remote_ipstr, g_remote_port);\n        goto free_ctx;\n    }\n    log_verbose(\"recv from %s#%hu, nrecv:%zd\", g_remote_ipstr, g_remote_port, nrecv);\n\n    ctx->nbytes += nrecv;\n\n    uint16_t msglen;\n    if (ctx->nbytes < 2 || ctx->nbytes < 2 + (msglen = ntohs(*(uint16_t *)buffer))) return;\n\n    ssize_t nsend = sendto(g_listen_fd, buffer + 2, msglen, 0, &ctx->srcaddr.sa, skaddr_len(&ctx->srcaddr));\n    if (nsend < 0 || verbose) {\n        char ip[IP6STRLEN];\n        uint16_t port;\n        skaddr_to_text(&ctx->srcaddr, ip, &port);\n        if (nsend < 0)\n            log_warning(\"send to %s#%hu: %m\", ip, port);\n        else\n            log_info(\"send to %s#%hu, nsend:%zd\", ip, port, nsend);\n    }\n\nfree_ctx:\n    free_ctx(ctx, evloop);\n}\n"
  },
  {
    "path": "libev/config.h",
    "content": "#pragma once\n\n#pragma GCC diagnostic ignored \"-Wcomment\"\n#pragma GCC diagnostic ignored \"-Wunused-function\"\n#pragma GCC diagnostic ignored \"-Wunused-parameter\"\n#pragma GCC diagnostic ignored \"-Wunused-variable\"\n#pragma GCC diagnostic ignored \"-Wunused-value\"\n#ifdef __clang__\n#pragma GCC diagnostic ignored \"-Wextern-initializer\"\n#endif\n\n/* libev-4.33 */\n#define EV_STANDALONE 1 /* manual configuration */\n#define EV_COMPAT3 0 /* remove compatible code */\n#define EV_VERIFY 0 /* remove verification code */\n#define EV_USE_FLOOR 1 /* use libm.floor() function */\n// #define EV_NO_SMP 1 /* disable multi-threads support */\n// #define EV_NO_THREADS 1 /* disable multi-threads support */\n#define EV_PERIODIC_ENABLE 0 /* disable ev_periodic watcher */\n#define EV_SIGNAL_ENABLE 0 /* disable ev_signal watcher */\n#define EV_CHILD_ENABLE 0 /* disable ev_child watcher */\n#define EV_STAT_ENABLE 0 /* disable ev_stat watcher */\n#define EV_IDLE_ENABLE 0 /* disable ev_idle watcher */\n#define EV_PREPARE_ENABLE 0 /* disable ev_prepare watcher */\n#define EV_CHECK_ENABLE 0 /* disable ev_check watcher */\n#define EV_EMBED_ENABLE 0 /* disable ev_embed watcher */\n#define EV_FORK_ENABLE 0 /* disable ev_fork watcher */\n#define EV_CLEANUP_ENABLE 0 /* disable ev_cleanup watcher */\n#define EV_ASYNC_ENABLE 0 /* disbale ev_async watcher */\n\n#define EV_USE_SELECT 0\n#define EV_USE_POLL 0\n#define EV_USE_EPOLL 1\n#define EV_USE_LINUXAIO 0\n#define EV_USE_IOURING 0\n#define EV_USE_KQUEUE 0\n#define EV_USE_PORT 0\n#define EV_USE_INOTIFY 0\n\n#define EV_USE_MONOTONIC 0\n#define EV_USE_REALTIME 0\n#define EV_USE_CLOCK_SYSCALL 0\n\n#define EV_USE_TIMERFD 0\n#define EV_USE_EVENTFD 0\n#define EV_USE_SIGNALFD 0\n\n#define EV_MINPRI 0\n#define EV_MAXPRI 0\n\n/* typedef struct */\ntypedef struct ev_loop  evloop_t;\ntypedef struct ev_io    evio_t;\ntypedef struct ev_timer evtimer_t;\n\n/* typedef callback */\ntypedef void (*evio_cb_t)(evloop_t *evloop, evio_t *watcher, int revents);\ntypedef void (*evtimer_cb_t)(evloop_t *evloop, evtimer_t *watcher, int revents);\n"
  },
  {
    "path": "libev/ev.c",
    "content": "/*\n * libev event processing core, watcher management\n *\n * Copyright (c) 2007-2019 Marc Alexander Lehmann <libev@schmorp.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modifica-\n * tion, are permitted provided that the following conditions are met:\n *\n *   1.  Redistributions of source code must retain the above copyright notice,\n *       this list of conditions and the following disclaimer.\n *\n *   2.  Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-\n * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\n * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-\n * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-\n * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Alternatively, the contents of this file may be used under the terms of\n * the GNU General Public License (\"GPL\") version 2 or any later version,\n * in which case the provisions of the GPL are applicable instead of\n * the above. If you wish to allow the use of your version of this file\n * only under the terms of the GPL and not to allow others to use your\n * version of this file under the BSD license, indicate your decision\n * by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL. If you do not delete the\n * provisions above, a recipient may use your version of this file under\n * either the BSD or the GPL.\n */\n\n#include \"config.h\"\n\n/* this big block deduces configuration from config.h */\n#ifndef EV_STANDALONE\n# ifdef EV_CONFIG_H\n#  include EV_CONFIG_H\n# else\n#  include \"config.h\"\n# endif\n\n# if HAVE_FLOOR\n#  ifndef EV_USE_FLOOR\n#   define EV_USE_FLOOR 1\n#  endif\n# endif\n\n# if HAVE_CLOCK_SYSCALL\n#  ifndef EV_USE_CLOCK_SYSCALL\n#   define EV_USE_CLOCK_SYSCALL 1\n#   ifndef EV_USE_REALTIME\n#    define EV_USE_REALTIME  0\n#   endif\n#   ifndef EV_USE_MONOTONIC\n#    define EV_USE_MONOTONIC 1\n#   endif\n#  endif\n# elif !defined EV_USE_CLOCK_SYSCALL\n#  define EV_USE_CLOCK_SYSCALL 0\n# endif\n\n# if HAVE_CLOCK_GETTIME\n#  ifndef EV_USE_MONOTONIC\n#   define EV_USE_MONOTONIC 1\n#  endif\n#  ifndef EV_USE_REALTIME\n#   define EV_USE_REALTIME  0\n#  endif\n# else\n#  ifndef EV_USE_MONOTONIC\n#   define EV_USE_MONOTONIC 0\n#  endif\n#  ifndef EV_USE_REALTIME\n#   define EV_USE_REALTIME  0\n#  endif\n# endif\n\n# if HAVE_NANOSLEEP\n#  ifndef EV_USE_NANOSLEEP\n#    define EV_USE_NANOSLEEP EV_FEATURE_OS\n#  endif\n# else\n#   undef EV_USE_NANOSLEEP\n#   define EV_USE_NANOSLEEP 0\n# endif\n\n# if HAVE_SELECT && HAVE_SYS_SELECT_H\n#  ifndef EV_USE_SELECT\n#   define EV_USE_SELECT EV_FEATURE_BACKENDS\n#  endif\n# else\n#  undef EV_USE_SELECT\n#  define EV_USE_SELECT 0\n# endif\n\n# if HAVE_POLL && HAVE_POLL_H\n#  ifndef EV_USE_POLL\n#   define EV_USE_POLL EV_FEATURE_BACKENDS\n#  endif\n# else\n#  undef EV_USE_POLL\n#  define EV_USE_POLL 0\n# endif\n   \n# if HAVE_EPOLL_CTL && HAVE_SYS_EPOLL_H\n#  ifndef EV_USE_EPOLL\n#   define EV_USE_EPOLL EV_FEATURE_BACKENDS\n#  endif\n# else\n#  undef EV_USE_EPOLL\n#  define EV_USE_EPOLL 0\n# endif\n   \n# if HAVE_LINUX_AIO_ABI_H\n#  ifndef EV_USE_LINUXAIO\n#   define EV_USE_LINUXAIO 0 /* was: EV_FEATURE_BACKENDS, always off by default */\n#  endif\n# else\n#  undef EV_USE_LINUXAIO\n#  define EV_USE_LINUXAIO 0\n# endif\n   \n# if HAVE_LINUX_FS_H && HAVE_SYS_TIMERFD_H && HAVE_KERNEL_RWF_T\n#  ifndef EV_USE_IOURING\n#   define EV_USE_IOURING EV_FEATURE_BACKENDS\n#  endif\n# else\n#  undef EV_USE_IOURING\n#  define EV_USE_IOURING 0\n# endif\n \n# if HAVE_KQUEUE && HAVE_SYS_EVENT_H\n#  ifndef EV_USE_KQUEUE\n#   define EV_USE_KQUEUE EV_FEATURE_BACKENDS\n#  endif\n# else\n#  undef EV_USE_KQUEUE\n#  define EV_USE_KQUEUE 0\n# endif\n   \n# if HAVE_PORT_H && HAVE_PORT_CREATE\n#  ifndef EV_USE_PORT\n#   define EV_USE_PORT EV_FEATURE_BACKENDS\n#  endif\n# else\n#  undef EV_USE_PORT\n#  define EV_USE_PORT 0\n# endif\n\n# if HAVE_INOTIFY_INIT && HAVE_SYS_INOTIFY_H\n#  ifndef EV_USE_INOTIFY\n#   define EV_USE_INOTIFY EV_FEATURE_OS\n#  endif\n# else\n#  undef EV_USE_INOTIFY\n#  define EV_USE_INOTIFY 0\n# endif\n\n# if HAVE_SIGNALFD && HAVE_SYS_SIGNALFD_H\n#  ifndef EV_USE_SIGNALFD\n#   define EV_USE_SIGNALFD EV_FEATURE_OS\n#  endif\n# else\n#  undef EV_USE_SIGNALFD\n#  define EV_USE_SIGNALFD 0\n# endif\n\n# if HAVE_EVENTFD\n#  ifndef EV_USE_EVENTFD\n#   define EV_USE_EVENTFD EV_FEATURE_OS\n#  endif\n# else\n#  undef EV_USE_EVENTFD\n#  define EV_USE_EVENTFD 0\n# endif\n\n# if HAVE_SYS_TIMERFD_H\n#  ifndef EV_USE_TIMERFD\n#   define EV_USE_TIMERFD EV_FEATURE_OS\n#  endif\n# else\n#  undef EV_USE_TIMERFD\n#  define EV_USE_TIMERFD 0\n# endif\n\n#endif\n\n/* OS X, in its infinite idiocy, actually HARDCODES\n * a limit of 1024 into their select. Where people have brains,\n * OS X engineers apparently have a vacuum. Or maybe they were\n * ordered to have a vacuum, or they do anything for money.\n * This might help. Or not.\n * Note that this must be defined early, as other include files\n * will rely on this define as well.\n */\n#define _DARWIN_UNLIMITED_SELECT 1\n\n#include <stdlib.h>\n#include <string.h>\n#include <fcntl.h>\n#include <stddef.h>\n\n#include <stdio.h>\n\n#include <assert.h>\n#include <errno.h>\n#include <sys/types.h>\n#include <time.h>\n#include <limits.h>\n\n#include <signal.h>\n\n#ifdef EV_H\n# include EV_H\n#else\n# include \"ev.h\"\n#endif\n\n#if EV_NO_THREADS\n# undef EV_NO_SMP\n# define EV_NO_SMP 1\n# undef ECB_NO_THREADS\n# define ECB_NO_THREADS 1\n#endif\n#if EV_NO_SMP\n# undef EV_NO_SMP\n# define ECB_NO_SMP 1\n#endif\n\n#ifndef _WIN32\n# include <sys/time.h>\n# include <sys/wait.h>\n# include <unistd.h>\n# include <syscall.h>\n#else\n# include <io.h>\n# define WIN32_LEAN_AND_MEAN\n# include <winsock2.h>\n# include <windows.h>\n# ifndef EV_SELECT_IS_WINSOCKET\n#  define EV_SELECT_IS_WINSOCKET 1\n# endif\n# undef EV_AVOID_STDIO\n#endif\n\n/* this block tries to deduce configuration from header-defined symbols and defaults */\n\n/* try to deduce the maximum number of signals on this platform */\n#if defined EV_NSIG\n/* use what's provided */\n#elif defined NSIG\n# define EV_NSIG (NSIG)\n#elif defined _NSIG\n# define EV_NSIG (_NSIG)\n#elif defined SIGMAX\n# define EV_NSIG (SIGMAX+1)\n#elif defined SIG_MAX\n# define EV_NSIG (SIG_MAX+1)\n#elif defined _SIG_MAX\n# define EV_NSIG (_SIG_MAX+1)\n#elif defined MAXSIG\n# define EV_NSIG (MAXSIG+1)\n#elif defined MAX_SIG\n# define EV_NSIG (MAX_SIG+1)\n#elif defined SIGARRAYSIZE\n# define EV_NSIG (SIGARRAYSIZE) /* Assume ary[SIGARRAYSIZE] */\n#elif defined _sys_nsig\n# define EV_NSIG (_sys_nsig) /* Solaris 2.5 */\n#else\n# define EV_NSIG (8 * sizeof (sigset_t) + 1)\n#endif\n\n#ifndef EV_USE_FLOOR\n# define EV_USE_FLOOR 0\n#endif\n\n#ifndef EV_USE_CLOCK_SYSCALL\n# if __linux && __GLIBC__ == 2 && __GLIBC_MINOR__ < 17\n#  define EV_USE_CLOCK_SYSCALL EV_FEATURE_OS\n# else\n#  define EV_USE_CLOCK_SYSCALL 0\n# endif\n#endif\n\n#if !(_POSIX_TIMERS > 0)\n# ifndef EV_USE_MONOTONIC\n#  define EV_USE_MONOTONIC 0\n# endif\n# ifndef EV_USE_REALTIME\n#  define EV_USE_REALTIME 0\n# endif\n#endif\n\n#ifndef EV_USE_MONOTONIC\n# if defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0\n#  define EV_USE_MONOTONIC EV_FEATURE_OS\n# else\n#  define EV_USE_MONOTONIC 0\n# endif\n#endif\n\n#ifndef EV_USE_REALTIME\n# define EV_USE_REALTIME !EV_USE_CLOCK_SYSCALL\n#endif\n\n#ifndef EV_USE_NANOSLEEP\n# if _POSIX_C_SOURCE >= 199309L\n#  define EV_USE_NANOSLEEP EV_FEATURE_OS\n# else\n#  define EV_USE_NANOSLEEP 0\n# endif\n#endif\n\n#ifndef EV_USE_SELECT\n# define EV_USE_SELECT EV_FEATURE_BACKENDS\n#endif\n\n#ifndef EV_USE_POLL\n# ifdef _WIN32\n#  define EV_USE_POLL 0\n# else\n#  define EV_USE_POLL EV_FEATURE_BACKENDS\n# endif\n#endif\n\n#ifndef EV_USE_EPOLL\n# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 4))\n#  define EV_USE_EPOLL EV_FEATURE_BACKENDS\n# else\n#  define EV_USE_EPOLL 0\n# endif\n#endif\n\n#ifndef EV_USE_KQUEUE\n# define EV_USE_KQUEUE 0\n#endif\n\n#ifndef EV_USE_PORT\n# define EV_USE_PORT 0\n#endif\n\n#ifndef EV_USE_LINUXAIO\n# if __linux /* libev currently assumes linux/aio_abi.h is always available on linux */\n#  define EV_USE_LINUXAIO 0 /* was: 1, always off by default */\n# else\n#  define EV_USE_LINUXAIO 0\n# endif\n#endif\n\n#ifndef EV_USE_IOURING\n# if __linux /* later checks might disable again */\n#  define EV_USE_IOURING 1\n# else\n#  define EV_USE_IOURING 0\n# endif\n#endif\n\n#ifndef EV_USE_INOTIFY\n# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 4))\n#  define EV_USE_INOTIFY EV_FEATURE_OS\n# else\n#  define EV_USE_INOTIFY 0\n# endif\n#endif\n\n#ifndef EV_PID_HASHSIZE\n# define EV_PID_HASHSIZE EV_FEATURE_DATA ? 16 : 1\n#endif\n\n#ifndef EV_INOTIFY_HASHSIZE\n# define EV_INOTIFY_HASHSIZE EV_FEATURE_DATA ? 16 : 1\n#endif\n\n#ifndef EV_USE_EVENTFD\n# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7))\n#  define EV_USE_EVENTFD EV_FEATURE_OS\n# else\n#  define EV_USE_EVENTFD 0\n# endif\n#endif\n\n#ifndef EV_USE_SIGNALFD\n# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7))\n#  define EV_USE_SIGNALFD EV_FEATURE_OS\n# else\n#  define EV_USE_SIGNALFD 0\n# endif\n#endif\n\n#ifndef EV_USE_TIMERFD\n# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8))\n#  define EV_USE_TIMERFD EV_FEATURE_OS\n# else\n#  define EV_USE_TIMERFD 0\n# endif\n#endif\n\n#if 0 /* debugging */\n# define EV_VERIFY 3\n# define EV_USE_4HEAP 1\n# define EV_HEAP_CACHE_AT 1\n#endif\n\n#ifndef EV_VERIFY\n# define EV_VERIFY (EV_FEATURE_API ? 1 : 0)\n#endif\n\n#ifndef EV_USE_4HEAP\n# define EV_USE_4HEAP EV_FEATURE_DATA\n#endif\n\n#ifndef EV_HEAP_CACHE_AT\n# define EV_HEAP_CACHE_AT EV_FEATURE_DATA\n#endif\n\n#ifdef __ANDROID__\n/* supposedly, android doesn't typedef fd_mask */\n# undef EV_USE_SELECT\n# define EV_USE_SELECT 0\n/* supposedly, we need to include syscall.h, not sys/syscall.h, so just disable */\n# undef EV_USE_CLOCK_SYSCALL\n# define EV_USE_CLOCK_SYSCALL 0\n#endif\n\n/* aix's poll.h seems to cause lots of trouble */\n#ifdef _AIX\n/* AIX has a completely broken poll.h header */\n# undef EV_USE_POLL\n# define EV_USE_POLL 0\n#endif\n\n/* on linux, we can use a (slow) syscall to avoid a dependency on pthread, */\n/* which makes programs even slower. might work on other unices, too. */\n#if EV_USE_CLOCK_SYSCALL\n# include <sys/syscall.h>\n# ifdef SYS_clock_gettime\n#  define clock_gettime(id, ts) syscall (SYS_clock_gettime, (id), (ts))\n#  undef EV_USE_MONOTONIC\n#  define EV_USE_MONOTONIC 1\n#  define EV_NEED_SYSCALL 1\n# else\n#  undef EV_USE_CLOCK_SYSCALL\n#  define EV_USE_CLOCK_SYSCALL 0\n# endif\n#endif\n\n/* this block fixes any misconfiguration where we know we run into trouble otherwise */\n\n#ifndef CLOCK_MONOTONIC\n# undef EV_USE_MONOTONIC\n# define EV_USE_MONOTONIC 0\n#endif\n\n#ifndef CLOCK_REALTIME\n# undef EV_USE_REALTIME\n# define EV_USE_REALTIME 0\n#endif\n\n#if !EV_STAT_ENABLE\n# undef EV_USE_INOTIFY\n# define EV_USE_INOTIFY 0\n#endif\n\n#if __linux && EV_USE_IOURING\n# include <linux/version.h>\n# if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0)\n#  undef EV_USE_IOURING\n#  define EV_USE_IOURING 0\n# endif\n#endif\n\n#if !EV_USE_NANOSLEEP\n/* hp-ux has it in sys/time.h, which we unconditionally include above */\n# if !defined _WIN32 && !defined __hpux\n#  include <sys/select.h>\n# endif\n#endif\n\n#if EV_USE_LINUXAIO\n# include <sys/syscall.h>\n# if SYS_io_getevents && EV_USE_EPOLL /* linuxaio backend requires epoll backend */\n#  define EV_NEED_SYSCALL 1\n# else\n#  undef EV_USE_LINUXAIO\n#  define EV_USE_LINUXAIO 0\n# endif\n#endif\n\n#if EV_USE_IOURING\n# include <sys/syscall.h>\n# if !SYS_io_uring_setup && __linux && !__alpha\n#  define SYS_io_uring_setup     425\n#  define SYS_io_uring_enter     426\n#  define SYS_io_uring_wregister 427\n# endif\n# if SYS_io_uring_setup && EV_USE_EPOLL /* iouring backend requires epoll backend */\n#  define EV_NEED_SYSCALL 1\n# else\n#  undef EV_USE_IOURING\n#  define EV_USE_IOURING 0\n# endif\n#endif\n\n#if EV_USE_INOTIFY\n# include <sys/statfs.h>\n# include <sys/inotify.h>\n/* some very old inotify.h headers don't have IN_DONT_FOLLOW */\n# ifndef IN_DONT_FOLLOW\n#  undef EV_USE_INOTIFY\n#  define EV_USE_INOTIFY 0\n# endif\n#endif\n\n#if EV_USE_EVENTFD\n/* our minimum requirement is glibc 2.7 which has the stub, but not the full header */\n# include <stdint.h>\n# ifndef EFD_NONBLOCK\n#  define EFD_NONBLOCK O_NONBLOCK\n# endif\n# ifndef EFD_CLOEXEC\n#  ifdef O_CLOEXEC\n#   define EFD_CLOEXEC O_CLOEXEC\n#  else\n#   define EFD_CLOEXEC 02000000\n#  endif\n# endif\nEV_CPP(extern \"C\") int (eventfd) (unsigned int initval, int flags);\n#endif\n\n#if EV_USE_SIGNALFD\n/* our minimum requirement is glibc 2.7 which has the stub, but not the full header */\n# include <stdint.h>\n# ifndef SFD_NONBLOCK\n#  define SFD_NONBLOCK O_NONBLOCK\n# endif\n# ifndef SFD_CLOEXEC\n#  ifdef O_CLOEXEC\n#   define SFD_CLOEXEC O_CLOEXEC\n#  else\n#   define SFD_CLOEXEC 02000000\n#  endif\n# endif\nEV_CPP (extern \"C\") int (signalfd) (int fd, const sigset_t *mask, int flags);\n\nstruct signalfd_siginfo\n{\n  uint32_t ssi_signo;\n  char pad[128 - sizeof (uint32_t)];\n};\n#endif\n\n/* for timerfd, libev core requires TFD_TIMER_CANCEL_ON_SET &c */\n#if EV_USE_TIMERFD\n# include <sys/timerfd.h>\n/* timerfd is only used for periodics */\n# if !(defined (TFD_TIMER_CANCEL_ON_SET) && defined (TFD_CLOEXEC) && defined (TFD_NONBLOCK)) || !EV_PERIODIC_ENABLE\n#  undef EV_USE_TIMERFD\n#  define EV_USE_TIMERFD 0\n# endif\n#endif\n\n/*****************************************************************************/\n\n#if EV_VERIFY >= 3\n# define EV_FREQUENT_CHECK ev_verify (EV_A)\n#else\n# define EV_FREQUENT_CHECK do { } while (0)\n#endif\n\n/*\n * This is used to work around floating point rounding problems.\n * This value is good at least till the year 4000.\n */\n#define MIN_INTERVAL  0.0001220703125 /* 1/2**13, good till 4000 */\n//#define MIN_INTERVAL  0.00000095367431640625 /* 1/2**20, good till 2200 */\n\n#define MIN_TIMEJUMP   1. /* minimum timejump that gets detected (if monotonic clock available) */\n#define MAX_BLOCKTIME  59.743 /* never wait longer than this time (to detect time jumps) */\n#define MAX_BLOCKTIME2 1500001.07 /* same, but when timerfd is used to detect jumps, also safe delay to not overflow */\n\n/* find a portable timestamp that is \"always\" in the future but fits into time_t.\n * this is quite hard, and we are mostly guessing - we handle 32 bit signed/unsigned time_t,\n * and sizes larger than 32 bit, and maybe the unlikely floating point time_t */\n#define EV_TSTAMP_HUGE \\\n  (sizeof (time_t) >= 8     ? 10000000000000.  \\\n   : 0 < (time_t)4294967295 ?     4294967295.  \\\n   :                              2147483647.) \\\n\n#ifndef EV_TS_CONST\n# define EV_TS_CONST(nv) nv\n# define EV_TS_TO_MSEC(a) a * 1e3 + 0.9999\n# define EV_TS_FROM_USEC(us) us * 1e-6\n# define EV_TV_SET(tv,t) do { tv.tv_sec = (long)t; tv.tv_usec = (long)((t - tv.tv_sec) * 1e6); } while (0)\n# define EV_TS_SET(ts,t) do { ts.tv_sec = (long)t; ts.tv_nsec = (long)((t - ts.tv_sec) * 1e9); } while (0)\n# define EV_TV_GET(tv) ((tv).tv_sec + (tv).tv_usec * 1e-6)\n# define EV_TS_GET(ts) ((ts).tv_sec + (ts).tv_nsec * 1e-9)\n#endif\n\n/* the following is ecb.h embedded into libev - use update_ev_c to update from an external copy */\n/* ECB.H BEGIN */\n/*\n * libecb - http://software.schmorp.de/pkg/libecb\n *\n * Copyright (©) 2009-2015,2018-2020 Marc Alexander Lehmann <libecb@schmorp.de>\n * Copyright (©) 2011 Emanuele Giaquinta\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modifica-\n * tion, are permitted provided that the following conditions are met:\n *\n *   1.  Redistributions of source code must retain the above copyright notice,\n *       this list of conditions and the following disclaimer.\n *\n *   2.  Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-\n * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\n * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-\n * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-\n * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Alternatively, the contents of this file may be used under the terms of\n * the GNU General Public License (\"GPL\") version 2 or any later version,\n * in which case the provisions of the GPL are applicable instead of\n * the above. If you wish to allow the use of your version of this file\n * only under the terms of the GPL and not to allow others to use your\n * version of this file under the BSD license, indicate your decision\n * by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL. If you do not delete the\n * provisions above, a recipient may use your version of this file under\n * either the BSD or the GPL.\n */\n\n#ifndef ECB_H\n#define ECB_H\n\n/* 16 bits major, 16 bits minor */\n#define ECB_VERSION 0x00010008\n\n#include <string.h> /* for memcpy */\n\n#if defined (_WIN32) && !defined (__MINGW32__)\n  typedef   signed char   int8_t;\n  typedef unsigned char  uint8_t;\n  typedef   signed char   int_fast8_t;\n  typedef unsigned char  uint_fast8_t;\n  typedef   signed short  int16_t;\n  typedef unsigned short uint16_t;\n  typedef   signed int    int_fast16_t;\n  typedef unsigned int   uint_fast16_t;\n  typedef   signed int    int32_t;\n  typedef unsigned int   uint32_t;\n  typedef   signed int    int_fast32_t;\n  typedef unsigned int   uint_fast32_t;\n  #if __GNUC__\n    typedef   signed long long int64_t;\n    typedef unsigned long long uint64_t;\n  #else /* _MSC_VER || __BORLANDC__ */\n    typedef   signed __int64   int64_t;\n    typedef unsigned __int64   uint64_t;\n  #endif\n  typedef  int64_t  int_fast64_t;\n  typedef uint64_t uint_fast64_t;\n  #ifdef _WIN64\n    #define ECB_PTRSIZE 8\n    typedef uint64_t uintptr_t;\n    typedef  int64_t  intptr_t;\n  #else\n    #define ECB_PTRSIZE 4\n    typedef uint32_t uintptr_t;\n    typedef  int32_t  intptr_t;\n  #endif\n#else\n  #include <inttypes.h>\n  #if (defined INTPTR_MAX ? INTPTR_MAX : ULONG_MAX) > 0xffffffffU\n    #define ECB_PTRSIZE 8\n  #else\n    #define ECB_PTRSIZE 4\n  #endif\n#endif\n\n#define ECB_GCC_AMD64 (__amd64 || __amd64__ || __x86_64 || __x86_64__)\n#define ECB_MSVC_AMD64 (_M_AMD64 || _M_X64)\n\n#ifndef ECB_OPTIMIZE_SIZE\n  #if __OPTIMIZE_SIZE__\n    #define ECB_OPTIMIZE_SIZE 1\n  #else\n    #define ECB_OPTIMIZE_SIZE 0\n  #endif\n#endif\n\n/* work around x32 idiocy by defining proper macros */\n#if ECB_GCC_AMD64 || ECB_MSVC_AMD64\n  #if _ILP32\n    #define ECB_AMD64_X32 1\n  #else\n    #define ECB_AMD64 1\n  #endif\n#endif\n\n/* many compilers define _GNUC_ to some versions but then only implement\n * what their idiot authors think are the \"more important\" extensions,\n * causing enormous grief in return for some better fake benchmark numbers.\n * or so.\n * we try to detect these and simply assume they are not gcc - if they have\n * an issue with that they should have done it right in the first place.\n */\n#if !defined __GNUC_MINOR__ || defined __INTEL_COMPILER || defined __SUNPRO_C || defined __SUNPRO_CC || defined __llvm__ || defined __clang__\n  #define ECB_GCC_VERSION(major,minor) 0\n#else\n  #define ECB_GCC_VERSION(major,minor) (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))\n#endif\n\n#define ECB_CLANG_VERSION(major,minor) (__clang_major__ > (major) || (__clang_major__ == (major) && __clang_minor__ >= (minor)))\n\n#if __clang__ && defined __has_builtin\n  #define ECB_CLANG_BUILTIN(x) __has_builtin (x)\n#else\n  #define ECB_CLANG_BUILTIN(x) 0\n#endif\n\n#if __clang__ && defined __has_extension\n  #define ECB_CLANG_EXTENSION(x) __has_extension (x)\n#else\n  #define ECB_CLANG_EXTENSION(x) 0\n#endif\n\n#define ECB_CPP   (__cplusplus+0)\n#define ECB_CPP11 (__cplusplus >= 201103L)\n#define ECB_CPP14 (__cplusplus >= 201402L)\n#define ECB_CPP17 (__cplusplus >= 201703L)\n\n#if ECB_CPP\n  #define ECB_C            0\n  #define ECB_STDC_VERSION 0\n#else\n  #define ECB_C            1\n  #define ECB_STDC_VERSION __STDC_VERSION__\n#endif\n\n#define ECB_C99   (ECB_STDC_VERSION >= 199901L)\n#define ECB_C11   (ECB_STDC_VERSION >= 201112L)\n#define ECB_C17   (ECB_STDC_VERSION >= 201710L)\n\n#if ECB_CPP\n  #define ECB_EXTERN_C extern \"C\"\n  #define ECB_EXTERN_C_BEG ECB_EXTERN_C {\n  #define ECB_EXTERN_C_END }\n#else\n  #define ECB_EXTERN_C extern\n  #define ECB_EXTERN_C_BEG\n  #define ECB_EXTERN_C_END\n#endif\n\n/*****************************************************************************/\n\n/* ECB_NO_THREADS - ecb is not used by multiple threads, ever */\n/* ECB_NO_SMP     - ecb might be used in multiple threads, but only on a single cpu */\n\n#if ECB_NO_THREADS\n  #define ECB_NO_SMP 1\n#endif\n\n#if ECB_NO_SMP\n  #define ECB_MEMORY_FENCE do { } while (0)\n#endif\n\n/* http://www-01.ibm.com/support/knowledgecenter/SSGH3R_13.1.0/com.ibm.xlcpp131.aix.doc/compiler_ref/compiler_builtins.html */\n#if __xlC__ && ECB_CPP\n  #include <builtins.h>\n#endif\n\n#if 1400 <= _MSC_VER\n  #include <intrin.h> /* fence functions _ReadBarrier, also bit search functions _BitScanReverse */\n#endif\n\n#ifndef ECB_MEMORY_FENCE\n  #if ECB_GCC_VERSION(2,5) || defined __INTEL_COMPILER || (__llvm__ && __GNUC__) || __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110\n    #if __i386 || __i386__\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\"lock; orb $0, -1(%%esp)\" : : : \"memory\")\n      #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ (\"\"                        : : : \"memory\")\n      #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ (\"\"                        : : : \"memory\")\n    #elif ECB_GCC_AMD64\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\"mfence\"   : : : \"memory\")\n      #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ (\"\"         : : : \"memory\")\n      #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ (\"\"         : : : \"memory\")\n    #elif __powerpc__ || __ppc__ || __powerpc64__ || __ppc64__\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\"sync\"     : : : \"memory\")\n    #elif defined __ARM_ARCH_2__ \\\n      || defined __ARM_ARCH_3__  || defined __ARM_ARCH_3M__  \\\n      || defined __ARM_ARCH_4__  || defined __ARM_ARCH_4T__  \\\n      || defined __ARM_ARCH_5__  || defined __ARM_ARCH_5E__  \\\n      || defined __ARM_ARCH_5T__ || defined __ARM_ARCH_5TE__ \\\n      || defined __ARM_ARCH_5TEJ__\n      /* should not need any, unless running old code on newer cpu - arm doesn't support that */\n      #define ECB_MEMORY_FENCE do { } while (0)\n    #elif defined __ARM_ARCH_6__  || defined __ARM_ARCH_6J__  \\\n       || defined __ARM_ARCH_6K__ || defined __ARM_ARCH_6ZK__ \\\n       || defined __ARM_ARCH_6T2__\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\"mcr p15,0,%0,c7,c10,5\" : : \"r\" (0) : \"memory\")\n    #elif defined __ARM_ARCH_7__  || defined __ARM_ARCH_7A__  \\\n       || defined __ARM_ARCH_7R__ || defined __ARM_ARCH_7M__\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\"dmb\"      : : : \"memory\")\n    #elif __aarch64__\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\"dmb ish\"  : : : \"memory\")\n    #elif (__sparc || __sparc__) && !(__sparc_v8__ || defined __sparcv8)\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\"membar #LoadStore | #LoadLoad | #StoreStore | #StoreLoad\" : : : \"memory\")\n      #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ (\"membar #LoadStore | #LoadLoad\"                            : : : \"memory\")\n      #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ (\"membar #LoadStore             | #StoreStore\")\n    #elif defined __s390__ || defined __s390x__\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\"bcr 15,0\" : : : \"memory\")\n    #elif defined __mips__\n      /* GNU/Linux emulates sync on mips1 architectures, so we force its use */\n      /* anybody else who still uses mips1 is supposed to send in their version, with detection code. */\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\".set mips2; sync; .set mips0\" : : : \"memory\")\n    #elif defined __alpha__\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\"mb\"       : : : \"memory\")\n    #elif defined __hppa__\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\"\"         : : : \"memory\")\n      #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ (\"\")\n    #elif defined __ia64__\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\"mf\"       : : : \"memory\")\n    #elif defined __m68k__\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\"\"         : : : \"memory\")\n    #elif defined __m88k__\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\"tb1 0,%%r0,128\" : : : \"memory\")\n    #elif defined __sh__\n      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (\"\"         : : : \"memory\")\n    #endif\n  #endif\n#endif\n\n#ifndef ECB_MEMORY_FENCE\n  #if ECB_GCC_VERSION(4,7)\n    /* see comment below (stdatomic.h) about the C11 memory model. */\n    #define ECB_MEMORY_FENCE         __atomic_thread_fence (__ATOMIC_SEQ_CST)\n    #define ECB_MEMORY_FENCE_ACQUIRE __atomic_thread_fence (__ATOMIC_ACQUIRE)\n    #define ECB_MEMORY_FENCE_RELEASE __atomic_thread_fence (__ATOMIC_RELEASE)\n\n  #elif ECB_CLANG_EXTENSION(c_atomic)\n    /* see comment below (stdatomic.h) about the C11 memory model. */\n    #define ECB_MEMORY_FENCE         __c11_atomic_thread_fence (__ATOMIC_SEQ_CST)\n    #define ECB_MEMORY_FENCE_ACQUIRE __c11_atomic_thread_fence (__ATOMIC_ACQUIRE)\n    #define ECB_MEMORY_FENCE_RELEASE __c11_atomic_thread_fence (__ATOMIC_RELEASE)\n\n  #elif ECB_GCC_VERSION(4,4) || defined __INTEL_COMPILER || defined __clang__\n    #define ECB_MEMORY_FENCE         __sync_synchronize ()\n  #elif _MSC_VER >= 1500 /* VC++ 2008 */\n    /* apparently, microsoft broke all the memory barrier stuff in Visual Studio 2008... */\n    #pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier)\n    #define ECB_MEMORY_FENCE         _ReadWriteBarrier (); MemoryBarrier()\n    #define ECB_MEMORY_FENCE_ACQUIRE _ReadWriteBarrier (); MemoryBarrier() /* according to msdn, _ReadBarrier is not a load fence */\n    #define ECB_MEMORY_FENCE_RELEASE _WriteBarrier (); MemoryBarrier()\n  #elif _MSC_VER >= 1400 /* VC++ 2005 */\n    #pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier)\n    #define ECB_MEMORY_FENCE         _ReadWriteBarrier ()\n    #define ECB_MEMORY_FENCE_ACQUIRE _ReadWriteBarrier () /* according to msdn, _ReadBarrier is not a load fence */\n    #define ECB_MEMORY_FENCE_RELEASE _WriteBarrier ()\n  #elif defined _WIN32\n    #include <WinNT.h>\n    #define ECB_MEMORY_FENCE         MemoryBarrier () /* actually just xchg on x86... scary */\n  #elif __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110\n    #include <mbarrier.h>\n    #define ECB_MEMORY_FENCE         __machine_rw_barrier  ()\n    #define ECB_MEMORY_FENCE_ACQUIRE __machine_acq_barrier ()\n    #define ECB_MEMORY_FENCE_RELEASE __machine_rel_barrier ()\n  #elif __xlC__\n    #define ECB_MEMORY_FENCE         __sync ()\n  #endif\n#endif\n\n#ifndef ECB_MEMORY_FENCE\n  #if ECB_C11 && !defined __STDC_NO_ATOMICS__\n    /* we assume that these memory fences work on all variables/all memory accesses, */\n    /* not just C11 atomics and atomic accesses */\n    #include <stdatomic.h>\n    #define ECB_MEMORY_FENCE         atomic_thread_fence (memory_order_seq_cst)\n    #define ECB_MEMORY_FENCE_ACQUIRE atomic_thread_fence (memory_order_acquire)\n    #define ECB_MEMORY_FENCE_RELEASE atomic_thread_fence (memory_order_release)\n  #endif\n#endif\n\n#ifndef ECB_MEMORY_FENCE\n  #if !ECB_AVOID_PTHREADS\n    /*\n     * if you get undefined symbol references to pthread_mutex_lock,\n     * or failure to find pthread.h, then you should implement\n     * the ECB_MEMORY_FENCE operations for your cpu/compiler\n     * OR provide pthread.h and link against the posix thread library\n     * of your system.\n     */\n    #include <pthread.h>\n    #define ECB_NEEDS_PTHREADS 1\n    #define ECB_MEMORY_FENCE_NEEDS_PTHREADS 1\n\n    static pthread_mutex_t ecb_mf_lock = PTHREAD_MUTEX_INITIALIZER;\n    #define ECB_MEMORY_FENCE do { pthread_mutex_lock (&ecb_mf_lock); pthread_mutex_unlock (&ecb_mf_lock); } while (0)\n  #endif\n#endif\n\n#if !defined ECB_MEMORY_FENCE_ACQUIRE && defined ECB_MEMORY_FENCE\n  #define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE\n#endif\n\n#if !defined ECB_MEMORY_FENCE_RELEASE && defined ECB_MEMORY_FENCE\n  #define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE\n#endif\n\n/*****************************************************************************/\n\n#if ECB_CPP\n  #define ecb_inline static inline\n#elif ECB_GCC_VERSION(2,5)\n  #define ecb_inline static __inline__\n#elif ECB_C99\n  #define ecb_inline static inline\n#else\n  #define ecb_inline static\n#endif\n\n#if ECB_GCC_VERSION(3,3)\n  #define ecb_restrict __restrict__\n#elif ECB_C99\n  #define ecb_restrict restrict\n#else\n  #define ecb_restrict\n#endif\n\ntypedef int ecb_bool;\n\n#define ECB_CONCAT_(a, b) a ## b\n#define ECB_CONCAT(a, b) ECB_CONCAT_(a, b)\n#define ECB_STRINGIFY_(a) # a\n#define ECB_STRINGIFY(a) ECB_STRINGIFY_(a)\n#define ECB_STRINGIFY_EXPR(expr) ((expr), ECB_STRINGIFY_ (expr))\n\n#define ecb_function_ ecb_inline\n\n#if ECB_GCC_VERSION(3,1) || ECB_CLANG_VERSION(2,8)\n  #define ecb_attribute(attrlist)        __attribute__ (attrlist)\n#else\n  #define ecb_attribute(attrlist)\n#endif\n\n#if ECB_GCC_VERSION(3,1) || ECB_CLANG_BUILTIN(__builtin_constant_p)\n  #define ecb_is_constant(expr)          __builtin_constant_p (expr)\n#else\n  /* possible C11 impl for integral types\n  typedef struct ecb_is_constant_struct ecb_is_constant_struct;\n  #define ecb_is_constant(expr)          _Generic ((1 ? (struct ecb_is_constant_struct *)0 : (void *)((expr) - (expr)), ecb_is_constant_struct *: 0, default: 1)) */\n\n  #define ecb_is_constant(expr)          0\n#endif\n\n#if ECB_GCC_VERSION(3,1) || ECB_CLANG_BUILTIN(__builtin_expect)\n  #define ecb_expect(expr,value)         __builtin_expect ((expr),(value))\n#else\n  #define ecb_expect(expr,value)         (expr)\n#endif\n\n#if ECB_GCC_VERSION(3,1) || ECB_CLANG_BUILTIN(__builtin_prefetch)\n  #define ecb_prefetch(addr,rw,locality) __builtin_prefetch (addr, rw, locality)\n#else\n  #define ecb_prefetch(addr,rw,locality)\n#endif\n\n/* no emulation for ecb_decltype */\n#if ECB_CPP11\n  // older implementations might have problems with decltype(x)::type, work around it\n  template<class T> struct ecb_decltype_t { typedef T type; };\n  #define ecb_decltype(x) ecb_decltype_t<decltype (x)>::type\n#elif ECB_GCC_VERSION(3,0) || ECB_CLANG_VERSION(2,8)\n  #define ecb_decltype(x) __typeof__ (x)\n#endif\n\n#if _MSC_VER >= 1300\n  #define ecb_deprecated __declspec (deprecated)\n#else\n  #define ecb_deprecated ecb_attribute ((__deprecated__))\n#endif\n\n#if _MSC_VER >= 1500\n  #define ecb_deprecated_message(msg) __declspec (deprecated (msg))\n#elif ECB_GCC_VERSION(4,5)\n  #define ecb_deprecated_message(msg) ecb_attribute ((__deprecated__ (msg))\n#else\n  #define ecb_deprecated_message(msg) ecb_deprecated\n#endif\n\n#if _MSC_VER >= 1400\n  #define ecb_noinline __declspec (noinline)\n#else\n  #define ecb_noinline ecb_attribute ((__noinline__))\n#endif\n\n#define ecb_unused     ecb_attribute ((__unused__))\n#define ecb_const      ecb_attribute ((__const__))\n#define ecb_pure       ecb_attribute ((__pure__))\n\n#if ECB_C11 || __IBMC_NORETURN\n  /* http://www-01.ibm.com/support/knowledgecenter/SSGH3R_13.1.0/com.ibm.xlcpp131.aix.doc/language_ref/noreturn.html */\n  #define ecb_noreturn   _Noreturn\n#elif ECB_CPP11\n  #define ecb_noreturn   [[noreturn]]\n#elif _MSC_VER >= 1200\n  /* http://msdn.microsoft.com/en-us/library/k6ktzx3s.aspx */\n  #define ecb_noreturn   __declspec (noreturn)\n#else\n  #define ecb_noreturn   ecb_attribute ((__noreturn__))\n#endif\n\n#if ECB_GCC_VERSION(4,3)\n  #define ecb_artificial ecb_attribute ((__artificial__))\n  #define ecb_hot        ecb_attribute ((__hot__))\n  #define ecb_cold       ecb_attribute ((__cold__))\n#else\n  #define ecb_artificial\n  #define ecb_hot\n  #define ecb_cold\n#endif\n\n/* put around conditional expressions if you are very sure that the  */\n/* expression is mostly true or mostly false. note that these return */\n/* booleans, not the expression.                                     */\n#define ecb_expect_false(expr) ecb_expect (!!(expr), 0)\n#define ecb_expect_true(expr)  ecb_expect (!!(expr), 1)\n/* for compatibility to the rest of the world */\n#define ecb_likely(expr)   ecb_expect_true  (expr)\n#define ecb_unlikely(expr) ecb_expect_false (expr)\n\n/* count trailing zero bits and count # of one bits */\n#if ECB_GCC_VERSION(3,4) \\\n    || (ECB_CLANG_BUILTIN(__builtin_clz) && ECB_CLANG_BUILTIN(__builtin_clzll) \\\n        && ECB_CLANG_BUILTIN(__builtin_ctz) && ECB_CLANG_BUILTIN(__builtin_ctzll) \\\n        && ECB_CLANG_BUILTIN(__builtin_popcount))\n  /* we assume int == 32 bit, long == 32 or 64 bit and long long == 64 bit */\n  #define ecb_ld32(x)      (__builtin_clz      (x) ^ 31)\n  #define ecb_ld64(x)      (__builtin_clzll    (x) ^ 63)\n  #define ecb_ctz32(x)      __builtin_ctz      (x)\n  #define ecb_ctz64(x)      __builtin_ctzll    (x)\n  #define ecb_popcount32(x) __builtin_popcount (x)\n  /* no popcountll */\n#else\n  ecb_function_ ecb_const int ecb_ctz32 (uint32_t x);\n  ecb_function_ ecb_const int\n  ecb_ctz32 (uint32_t x)\n  {\n#if 1400 <= _MSC_VER && (_M_IX86 || _M_X64 || _M_IA64 || _M_ARM)\n    unsigned long r;\n    _BitScanForward (&r, x);\n    return (int)r;\n#else\n    int r = 0;\n\n    x &= ~x + 1; /* this isolates the lowest bit */\n\n#if ECB_branchless_on_i386\n    r += !!(x & 0xaaaaaaaa) << 0;\n    r += !!(x & 0xcccccccc) << 1;\n    r += !!(x & 0xf0f0f0f0) << 2;\n    r += !!(x & 0xff00ff00) << 3;\n    r += !!(x & 0xffff0000) << 4;\n#else\n    if (x & 0xaaaaaaaa) r +=  1;\n    if (x & 0xcccccccc) r +=  2;\n    if (x & 0xf0f0f0f0) r +=  4;\n    if (x & 0xff00ff00) r +=  8;\n    if (x & 0xffff0000) r += 16;\n#endif\n\n    return r;\n#endif\n  }\n\n  ecb_function_ ecb_const int ecb_ctz64 (uint64_t x);\n  ecb_function_ ecb_const int\n  ecb_ctz64 (uint64_t x)\n  {\n#if 1400 <= _MSC_VER && (_M_X64 || _M_IA64 || _M_ARM)\n    unsigned long r;\n    _BitScanForward64 (&r, x);\n    return (int)r;\n#else\n    int shift = x & 0xffffffff ? 0 : 32;\n    return ecb_ctz32 (x >> shift) + shift;\n#endif\n  }\n\n  ecb_function_ ecb_const int ecb_popcount32 (uint32_t x);\n  ecb_function_ ecb_const int\n  ecb_popcount32 (uint32_t x)\n  {\n    x -=  (x >> 1) & 0x55555555;\n    x  = ((x >> 2) & 0x33333333) + (x & 0x33333333);\n    x  = ((x >> 4) + x) & 0x0f0f0f0f;\n    x *= 0x01010101;\n\n    return x >> 24;\n  }\n\n  ecb_function_ ecb_const int ecb_ld32 (uint32_t x);\n  ecb_function_ ecb_const int ecb_ld32 (uint32_t x)\n  {\n#if 1400 <= _MSC_VER && (_M_IX86 || _M_X64 || _M_IA64 || _M_ARM)\n    unsigned long r;\n    _BitScanReverse (&r, x);\n    return (int)r;\n#else\n    int r = 0;\n\n    if (x >> 16) { x >>= 16; r += 16; }\n    if (x >>  8) { x >>=  8; r +=  8; }\n    if (x >>  4) { x >>=  4; r +=  4; }\n    if (x >>  2) { x >>=  2; r +=  2; }\n    if (x >>  1) {           r +=  1; }\n\n    return r;\n#endif\n  }\n\n  ecb_function_ ecb_const int ecb_ld64 (uint64_t x);\n  ecb_function_ ecb_const int ecb_ld64 (uint64_t x)\n  {\n#if 1400 <= _MSC_VER && (_M_X64 || _M_IA64 || _M_ARM)\n    unsigned long r;\n    _BitScanReverse64 (&r, x);\n    return (int)r;\n#else\n    int r = 0;\n\n    if (x >> 32) { x >>= 32; r += 32; }\n\n    return r + ecb_ld32 (x);\n#endif\n  }\n#endif\n\necb_function_ ecb_const ecb_bool ecb_is_pot32 (uint32_t x);\necb_function_ ecb_const ecb_bool ecb_is_pot32 (uint32_t x) { return !(x & (x - 1)); }\necb_function_ ecb_const ecb_bool ecb_is_pot64 (uint64_t x);\necb_function_ ecb_const ecb_bool ecb_is_pot64 (uint64_t x) { return !(x & (x - 1)); }\n\necb_function_ ecb_const uint8_t  ecb_bitrev8  (uint8_t  x);\necb_function_ ecb_const uint8_t  ecb_bitrev8  (uint8_t  x)\n{\n  return (  (x * 0x0802U & 0x22110U)\n          | (x * 0x8020U & 0x88440U)) * 0x10101U >> 16;\n}\n\necb_function_ ecb_const uint16_t ecb_bitrev16 (uint16_t x);\necb_function_ ecb_const uint16_t ecb_bitrev16 (uint16_t x)\n{\n  x = ((x >>  1) &     0x5555) | ((x &     0x5555) <<  1);\n  x = ((x >>  2) &     0x3333) | ((x &     0x3333) <<  2);\n  x = ((x >>  4) &     0x0f0f) | ((x &     0x0f0f) <<  4);\n  x = ( x >>  8              ) | ( x               <<  8);\n\n  return x;\n}\n\necb_function_ ecb_const uint32_t ecb_bitrev32 (uint32_t x);\necb_function_ ecb_const uint32_t ecb_bitrev32 (uint32_t x)\n{\n  x = ((x >>  1) & 0x55555555) | ((x & 0x55555555) <<  1);\n  x = ((x >>  2) & 0x33333333) | ((x & 0x33333333) <<  2);\n  x = ((x >>  4) & 0x0f0f0f0f) | ((x & 0x0f0f0f0f) <<  4);\n  x = ((x >>  8) & 0x00ff00ff) | ((x & 0x00ff00ff) <<  8);\n  x = ( x >> 16              ) | ( x               << 16);\n\n  return x;\n}\n\n/* popcount64 is only available on 64 bit cpus as gcc builtin */\n/* so for this version we are lazy */\necb_function_ ecb_const int ecb_popcount64 (uint64_t x);\necb_function_ ecb_const int\necb_popcount64 (uint64_t x)\n{\n  return ecb_popcount32 (x) + ecb_popcount32 (x >> 32);\n}\n\necb_inline ecb_const uint8_t  ecb_rotl8  (uint8_t  x, unsigned int count);\necb_inline ecb_const uint8_t  ecb_rotr8  (uint8_t  x, unsigned int count);\necb_inline ecb_const uint16_t ecb_rotl16 (uint16_t x, unsigned int count);\necb_inline ecb_const uint16_t ecb_rotr16 (uint16_t x, unsigned int count);\necb_inline ecb_const uint32_t ecb_rotl32 (uint32_t x, unsigned int count);\necb_inline ecb_const uint32_t ecb_rotr32 (uint32_t x, unsigned int count);\necb_inline ecb_const uint64_t ecb_rotl64 (uint64_t x, unsigned int count);\necb_inline ecb_const uint64_t ecb_rotr64 (uint64_t x, unsigned int count);\n\necb_inline ecb_const uint8_t  ecb_rotl8  (uint8_t  x, unsigned int count) { return (x >> ( 8 - count)) | (x << count); }\necb_inline ecb_const uint8_t  ecb_rotr8  (uint8_t  x, unsigned int count) { return (x << ( 8 - count)) | (x >> count); }\necb_inline ecb_const uint16_t ecb_rotl16 (uint16_t x, unsigned int count) { return (x >> (16 - count)) | (x << count); }\necb_inline ecb_const uint16_t ecb_rotr16 (uint16_t x, unsigned int count) { return (x << (16 - count)) | (x >> count); }\necb_inline ecb_const uint32_t ecb_rotl32 (uint32_t x, unsigned int count) { return (x >> (32 - count)) | (x << count); }\necb_inline ecb_const uint32_t ecb_rotr32 (uint32_t x, unsigned int count) { return (x << (32 - count)) | (x >> count); }\necb_inline ecb_const uint64_t ecb_rotl64 (uint64_t x, unsigned int count) { return (x >> (64 - count)) | (x << count); }\necb_inline ecb_const uint64_t ecb_rotr64 (uint64_t x, unsigned int count) { return (x << (64 - count)) | (x >> count); }\n\n#if ECB_CPP\n\ninline uint8_t  ecb_ctz (uint8_t  v) { return ecb_ctz32 (v); }\ninline uint16_t ecb_ctz (uint16_t v) { return ecb_ctz32 (v); }\ninline uint32_t ecb_ctz (uint32_t v) { return ecb_ctz32 (v); }\ninline uint64_t ecb_ctz (uint64_t v) { return ecb_ctz64 (v); }\n\ninline bool ecb_is_pot (uint8_t  v) { return ecb_is_pot32 (v); }\ninline bool ecb_is_pot (uint16_t v) { return ecb_is_pot32 (v); }\ninline bool ecb_is_pot (uint32_t v) { return ecb_is_pot32 (v); }\ninline bool ecb_is_pot (uint64_t v) { return ecb_is_pot64 (v); }\n\ninline int ecb_ld (uint8_t  v) { return ecb_ld32 (v); }\ninline int ecb_ld (uint16_t v) { return ecb_ld32 (v); }\ninline int ecb_ld (uint32_t v) { return ecb_ld32 (v); }\ninline int ecb_ld (uint64_t v) { return ecb_ld64 (v); }\n\ninline int ecb_popcount (uint8_t  v) { return ecb_popcount32 (v); }\ninline int ecb_popcount (uint16_t v) { return ecb_popcount32 (v); }\ninline int ecb_popcount (uint32_t v) { return ecb_popcount32 (v); }\ninline int ecb_popcount (uint64_t v) { return ecb_popcount64 (v); }\n\ninline uint8_t  ecb_bitrev (uint8_t  v) { return ecb_bitrev8  (v); }\ninline uint16_t ecb_bitrev (uint16_t v) { return ecb_bitrev16 (v); }\ninline uint32_t ecb_bitrev (uint32_t v) { return ecb_bitrev32 (v); }\n\ninline uint8_t  ecb_rotl (uint8_t  v, unsigned int count) { return ecb_rotl8  (v, count); }\ninline uint16_t ecb_rotl (uint16_t v, unsigned int count) { return ecb_rotl16 (v, count); }\ninline uint32_t ecb_rotl (uint32_t v, unsigned int count) { return ecb_rotl32 (v, count); }\ninline uint64_t ecb_rotl (uint64_t v, unsigned int count) { return ecb_rotl64 (v, count); }\n\ninline uint8_t  ecb_rotr (uint8_t  v, unsigned int count) { return ecb_rotr8  (v, count); }\ninline uint16_t ecb_rotr (uint16_t v, unsigned int count) { return ecb_rotr16 (v, count); }\ninline uint32_t ecb_rotr (uint32_t v, unsigned int count) { return ecb_rotr32 (v, count); }\ninline uint64_t ecb_rotr (uint64_t v, unsigned int count) { return ecb_rotr64 (v, count); }\n\n#endif\n\n#if ECB_GCC_VERSION(4,3) || (ECB_CLANG_BUILTIN(__builtin_bswap32) && ECB_CLANG_BUILTIN(__builtin_bswap64))\n  #if ECB_GCC_VERSION(4,8) || ECB_CLANG_BUILTIN(__builtin_bswap16)\n  #define ecb_bswap16(x)  __builtin_bswap16 (x)\n  #else\n  #define ecb_bswap16(x) (__builtin_bswap32 (x) >> 16)\n  #endif\n  #define ecb_bswap32(x)  __builtin_bswap32 (x)\n  #define ecb_bswap64(x)  __builtin_bswap64 (x)\n#elif _MSC_VER\n  #include <stdlib.h>\n  #define ecb_bswap16(x) ((uint16_t)_byteswap_ushort ((uint16_t)(x)))\n  #define ecb_bswap32(x) ((uint32_t)_byteswap_ulong  ((uint32_t)(x)))\n  #define ecb_bswap64(x) ((uint64_t)_byteswap_uint64 ((uint64_t)(x)))\n#else\n  ecb_function_ ecb_const uint16_t ecb_bswap16 (uint16_t x);\n  ecb_function_ ecb_const uint16_t\n  ecb_bswap16 (uint16_t x)\n  {\n    return ecb_rotl16 (x, 8);\n  }\n\n  ecb_function_ ecb_const uint32_t ecb_bswap32 (uint32_t x);\n  ecb_function_ ecb_const uint32_t\n  ecb_bswap32 (uint32_t x)\n  {\n    return (((uint32_t)ecb_bswap16 (x)) << 16) | ecb_bswap16 (x >> 16);\n  }\n\n  ecb_function_ ecb_const uint64_t ecb_bswap64 (uint64_t x);\n  ecb_function_ ecb_const uint64_t\n  ecb_bswap64 (uint64_t x)\n  {\n    return (((uint64_t)ecb_bswap32 (x)) << 32) | ecb_bswap32 (x >> 32);\n  }\n#endif\n\n#if ECB_GCC_VERSION(4,5) || ECB_CLANG_BUILTIN(__builtin_unreachable)\n  #define ecb_unreachable() __builtin_unreachable ()\n#else\n  /* this seems to work fine, but gcc always emits a warning for it :/ */\n  ecb_inline ecb_noreturn void ecb_unreachable (void);\n  ecb_inline ecb_noreturn void ecb_unreachable (void) { }\n#endif\n\n/* try to tell the compiler that some condition is definitely true */\n#define ecb_assume(cond) if (!(cond)) ecb_unreachable (); else 0\n\necb_inline ecb_const uint32_t ecb_byteorder_helper (void);\necb_inline ecb_const uint32_t\necb_byteorder_helper (void)\n{\n  /* the union code still generates code under pressure in gcc, */\n  /* but less than using pointers, and always seems to */\n  /* successfully return a constant. */\n  /* the reason why we have this horrible preprocessor mess */\n  /* is to avoid it in all cases, at least on common architectures */\n  /* or when using a recent enough gcc version (>= 4.6) */\n#if (defined __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) \\\n    || ((__i386 || __i386__ || _M_IX86 || ECB_GCC_AMD64 || ECB_MSVC_AMD64) && !__VOS__)\n  #define ECB_LITTLE_ENDIAN 1\n  return 0x44332211;\n#elif (defined __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) \\\n      || ((__AARCH64EB__ || __MIPSEB__ || __ARMEB__) && !__VOS__)\n  #define ECB_BIG_ENDIAN 1\n  return 0x11223344;\n#else\n  union\n  {\n    uint8_t c[4];\n    uint32_t u;\n  } u = { 0x11, 0x22, 0x33, 0x44 };\n  return u.u;\n#endif\n}\n\necb_inline ecb_const ecb_bool ecb_big_endian    (void);\necb_inline ecb_const ecb_bool ecb_big_endian    (void) { return ecb_byteorder_helper () == 0x11223344; }\necb_inline ecb_const ecb_bool ecb_little_endian (void);\necb_inline ecb_const ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () == 0x44332211; }\n\n/*****************************************************************************/\n/* unaligned load/store */\n\necb_inline uint_fast16_t ecb_be_u16_to_host (uint_fast16_t v) { return ecb_little_endian () ? ecb_bswap16 (v) : v; }\necb_inline uint_fast32_t ecb_be_u32_to_host (uint_fast32_t v) { return ecb_little_endian () ? ecb_bswap32 (v) : v; }\necb_inline uint_fast64_t ecb_be_u64_to_host (uint_fast64_t v) { return ecb_little_endian () ? ecb_bswap64 (v) : v; }\n\necb_inline uint_fast16_t ecb_le_u16_to_host (uint_fast16_t v) { return ecb_big_endian    () ? ecb_bswap16 (v) : v; }\necb_inline uint_fast32_t ecb_le_u32_to_host (uint_fast32_t v) { return ecb_big_endian    () ? ecb_bswap32 (v) : v; }\necb_inline uint_fast64_t ecb_le_u64_to_host (uint_fast64_t v) { return ecb_big_endian    () ? ecb_bswap64 (v) : v; }\n\necb_inline uint_fast16_t ecb_peek_u16_u (const void *ptr) { uint16_t v; memcpy (&v, ptr, sizeof (v)); return v; }\necb_inline uint_fast32_t ecb_peek_u32_u (const void *ptr) { uint32_t v; memcpy (&v, ptr, sizeof (v)); return v; }\necb_inline uint_fast64_t ecb_peek_u64_u (const void *ptr) { uint64_t v; memcpy (&v, ptr, sizeof (v)); return v; }\n\necb_inline uint_fast16_t ecb_peek_be_u16_u (const void *ptr) { return ecb_be_u16_to_host (ecb_peek_u16_u (ptr)); }\necb_inline uint_fast32_t ecb_peek_be_u32_u (const void *ptr) { return ecb_be_u32_to_host (ecb_peek_u32_u (ptr)); }\necb_inline uint_fast64_t ecb_peek_be_u64_u (const void *ptr) { return ecb_be_u64_to_host (ecb_peek_u64_u (ptr)); }\n\necb_inline uint_fast16_t ecb_peek_le_u16_u (const void *ptr) { return ecb_le_u16_to_host (ecb_peek_u16_u (ptr)); }\necb_inline uint_fast32_t ecb_peek_le_u32_u (const void *ptr) { return ecb_le_u32_to_host (ecb_peek_u32_u (ptr)); }\necb_inline uint_fast64_t ecb_peek_le_u64_u (const void *ptr) { return ecb_le_u64_to_host (ecb_peek_u64_u (ptr)); }\n\necb_inline uint_fast16_t ecb_host_to_be_u16 (uint_fast16_t v) { return ecb_little_endian () ? ecb_bswap16 (v) : v; }\necb_inline uint_fast32_t ecb_host_to_be_u32 (uint_fast32_t v) { return ecb_little_endian () ? ecb_bswap32 (v) : v; }\necb_inline uint_fast64_t ecb_host_to_be_u64 (uint_fast64_t v) { return ecb_little_endian () ? ecb_bswap64 (v) : v; }\n\necb_inline uint_fast16_t ecb_host_to_le_u16 (uint_fast16_t v) { return ecb_big_endian    () ? ecb_bswap16 (v) : v; }\necb_inline uint_fast32_t ecb_host_to_le_u32 (uint_fast32_t v) { return ecb_big_endian    () ? ecb_bswap32 (v) : v; }\necb_inline uint_fast64_t ecb_host_to_le_u64 (uint_fast64_t v) { return ecb_big_endian    () ? ecb_bswap64 (v) : v; }\n\necb_inline void ecb_poke_u16_u (void *ptr, uint16_t v) { memcpy (ptr, &v, sizeof (v)); }\necb_inline void ecb_poke_u32_u (void *ptr, uint32_t v) { memcpy (ptr, &v, sizeof (v)); }\necb_inline void ecb_poke_u64_u (void *ptr, uint64_t v) { memcpy (ptr, &v, sizeof (v)); }\n\necb_inline void ecb_poke_be_u16_u (void *ptr, uint_fast16_t v) { ecb_poke_u16_u (ptr, ecb_host_to_be_u16 (v)); }\necb_inline void ecb_poke_be_u32_u (void *ptr, uint_fast32_t v) { ecb_poke_u32_u (ptr, ecb_host_to_be_u32 (v)); }\necb_inline void ecb_poke_be_u64_u (void *ptr, uint_fast64_t v) { ecb_poke_u64_u (ptr, ecb_host_to_be_u64 (v)); }\n                                                                                                \necb_inline void ecb_poke_le_u16_u (void *ptr, uint_fast16_t v) { ecb_poke_u16_u (ptr, ecb_host_to_le_u16 (v)); }\necb_inline void ecb_poke_le_u32_u (void *ptr, uint_fast32_t v) { ecb_poke_u32_u (ptr, ecb_host_to_le_u32 (v)); }\necb_inline void ecb_poke_le_u64_u (void *ptr, uint_fast64_t v) { ecb_poke_u64_u (ptr, ecb_host_to_le_u64 (v)); }\n\n#if ECB_CPP\n\ninline uint8_t  ecb_bswap (uint8_t  v) { return v; }\ninline uint16_t ecb_bswap (uint16_t v) { return ecb_bswap16 (v); }\ninline uint32_t ecb_bswap (uint32_t v) { return ecb_bswap32 (v); }\ninline uint64_t ecb_bswap (uint64_t v) { return ecb_bswap64 (v); }\n\ntemplate<typename T> inline T ecb_be_to_host (T v) { return ecb_little_endian () ? ecb_bswap (v) : v; }\ntemplate<typename T> inline T ecb_le_to_host (T v) { return ecb_big_endian    () ? ecb_bswap (v) : v; }\ntemplate<typename T> inline T ecb_peek       (const void *ptr) { return *(const T *)ptr; }\ntemplate<typename T> inline T ecb_peek_be    (const void *ptr) { return ecb_be_to_host (ecb_peek  <T> (ptr)); }\ntemplate<typename T> inline T ecb_peek_le    (const void *ptr) { return ecb_le_to_host (ecb_peek  <T> (ptr)); }\ntemplate<typename T> inline T ecb_peek_u     (const void *ptr) { T v; memcpy (&v, ptr, sizeof (v)); return v; }\ntemplate<typename T> inline T ecb_peek_be_u  (const void *ptr) { return ecb_be_to_host (ecb_peek_u<T> (ptr)); }\ntemplate<typename T> inline T ecb_peek_le_u  (const void *ptr) { return ecb_le_to_host (ecb_peek_u<T> (ptr)); }\n\ntemplate<typename T> inline T ecb_host_to_be (T v) { return ecb_little_endian () ? ecb_bswap (v) : v; }\ntemplate<typename T> inline T ecb_host_to_le (T v) { return ecb_big_endian    () ? ecb_bswap (v) : v; }\ntemplate<typename T> inline void ecb_poke      (void *ptr, T v) { *(T *)ptr = v; }\ntemplate<typename T> inline void ecb_poke_be   (void *ptr, T v) { return ecb_poke  <T> (ptr, ecb_host_to_be (v)); }\ntemplate<typename T> inline void ecb_poke_le   (void *ptr, T v) { return ecb_poke  <T> (ptr, ecb_host_to_le (v)); }\ntemplate<typename T> inline void ecb_poke_u    (void *ptr, T v) { memcpy (ptr, &v, sizeof (v)); }\ntemplate<typename T> inline void ecb_poke_be_u (void *ptr, T v) { return ecb_poke_u<T> (ptr, ecb_host_to_be (v)); }\ntemplate<typename T> inline void ecb_poke_le_u (void *ptr, T v) { return ecb_poke_u<T> (ptr, ecb_host_to_le (v)); }\n\n#endif\n\n/*****************************************************************************/\n\n#if ECB_GCC_VERSION(3,0) || ECB_C99\n  #define ecb_mod(m,n) ((m) % (n) + ((m) % (n) < 0 ? (n) : 0))\n#else\n  #define ecb_mod(m,n) ((m) < 0 ? ((n) - 1 - ((-1 - (m)) % (n))) : ((m) % (n)))\n#endif\n\n#if ECB_CPP\n  template<typename T>\n  static inline T ecb_div_rd (T val, T div)\n  {\n    return val < 0 ? - ((-val + div - 1) / div) : (val          ) / div;\n  }\n  template<typename T>\n  static inline T ecb_div_ru (T val, T div)\n  {\n    return val < 0 ? - ((-val          ) / div) : (val + div - 1) / div;\n  }\n#else\n  #define ecb_div_rd(val,div) ((val) < 0 ? - ((-(val) + (div) - 1) / (div)) : ((val)            ) / (div))\n  #define ecb_div_ru(val,div) ((val) < 0 ? - ((-(val)            ) / (div)) : ((val) + (div) - 1) / (div))\n#endif\n\n#if ecb_cplusplus_does_not_suck\n  /* does not work for local types (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm) */\n  template<typename T, int N>\n  static inline int ecb_array_length (const T (&arr)[N])\n  {\n    return N;\n  }\n#else\n  #define ecb_array_length(name) (sizeof (name) / sizeof (name [0]))\n#endif\n\n/*****************************************************************************/\n\necb_function_ ecb_const uint32_t ecb_binary16_to_binary32 (uint32_t x);\necb_function_ ecb_const uint32_t\necb_binary16_to_binary32 (uint32_t x)\n{\n  unsigned int s = (x & 0x8000) << (31 - 15);\n  int          e = (x >> 10) & 0x001f;\n  unsigned int m =  x        & 0x03ff;\n\n  if (ecb_expect_false (e == 31))\n    /* infinity or NaN */\n    e = 255 - (127 - 15);\n  else if (ecb_expect_false (!e))\n    {\n      if (ecb_expect_true (!m))\n        /* zero, handled by code below by forcing e to 0 */\n        e = 0 - (127 - 15);\n      else\n        {\n          /* subnormal, renormalise */\n          unsigned int s = 10 - ecb_ld32 (m);\n\n          m = (m << s) & 0x3ff; /* mask implicit bit */\n          e -= s - 1;\n        }\n    }\n\n  /* e and m now are normalised, or zero, (or inf or nan) */\n  e += 127 - 15;\n\n  return s | (e << 23) | (m << (23 - 10));\n}\n\necb_function_ ecb_const uint16_t ecb_binary32_to_binary16 (uint32_t x);\necb_function_ ecb_const uint16_t\necb_binary32_to_binary16 (uint32_t x)\n{\n  unsigned int s =  (x >> 16) & 0x00008000; /* sign bit, the easy part */\n  unsigned int e = ((x >> 23) & 0x000000ff) - (127 - 15); /* the desired exponent */\n  unsigned int m =   x        & 0x007fffff;\n\n  x &= 0x7fffffff;\n\n  /* if it's within range of binary16 normals, use fast path */\n  if (ecb_expect_true (0x38800000 <= x && x <= 0x477fefff))\n    {\n      /* mantissa round-to-even */\n      m += 0x00000fff + ((m >> (23 - 10)) & 1);\n\n      /* handle overflow */\n      if (ecb_expect_false (m >= 0x00800000))\n        {\n          m >>= 1;\n          e +=  1;\n        }\n\n      return s | (e << 10) | (m >> (23 - 10));\n    }\n\n  /* handle large numbers and infinity */\n  if (ecb_expect_true (0x477fefff < x && x <= 0x7f800000))\n    return s | 0x7c00;\n\n  /* handle zero, subnormals and small numbers */\n  if (ecb_expect_true (x < 0x38800000))\n    {\n      /* zero */\n      if (ecb_expect_true (!x))\n        return s;\n\n      /* handle subnormals */\n\n      /* too small, will be zero */\n      if (e < (unsigned)(14 - 24)) /* might not be sharp, but is good enough */\n        return s;\n\n      m |= 0x00800000; /* make implicit bit explicit */\n\n      /* very tricky - we need to round to the nearest e (+10) bit value */\n      {\n        unsigned int bits = 14 - e;\n        unsigned int half = (1 << (bits - 1)) - 1;\n        unsigned int even = (m >> bits) & 1;\n\n        /* if this overflows, we will end up with a normalised number */\n        m = (m + half + even) >> bits;\n      }\n\n      return s | m;\n    }\n\n  /* handle NaNs, preserve leftmost nan bits, but make sure we don't turn them into infinities */\n  m >>= 13;\n\n  return s | 0x7c00 | m | !m;\n}\n\n/*******************************************************************************/\n/* floating point stuff, can be disabled by defining ECB_NO_LIBM */\n\n/* basically, everything uses \"ieee pure-endian\" floating point numbers */\n/* the only noteworthy exception is ancient armle, which uses order 43218765 */\n#if 0 \\\n    || __i386 || __i386__ \\\n    || ECB_GCC_AMD64 \\\n    || __powerpc__ || __ppc__ || __powerpc64__ || __ppc64__ \\\n    || defined __s390__ || defined __s390x__ \\\n    || defined __mips__ \\\n    || defined __alpha__ \\\n    || defined __hppa__ \\\n    || defined __ia64__ \\\n    || defined __m68k__ \\\n    || defined __m88k__ \\\n    || defined __sh__ \\\n    || defined _M_IX86 || defined ECB_MSVC_AMD64 || defined _M_IA64 \\\n    || (defined __arm__ && (defined __ARM_EABI__ || defined __EABI__ || defined __VFP_FP__ || defined _WIN32_WCE || defined __ANDROID__)) \\\n    || defined __aarch64__\n  #define ECB_STDFP 1\n#else\n  #define ECB_STDFP 0\n#endif\n\n#ifndef ECB_NO_LIBM\n\n  #include <math.h> /* for frexp*, ldexp*, INFINITY, NAN */\n\n  /* only the oldest of old doesn't have this one. solaris. */\n  #ifdef INFINITY\n    #define ECB_INFINITY INFINITY\n  #else\n    #define ECB_INFINITY HUGE_VAL\n  #endif\n\n  #ifdef NAN\n    #define ECB_NAN NAN\n  #else\n    #define ECB_NAN ECB_INFINITY\n  #endif\n\n  #if ECB_C99 || _XOPEN_VERSION >= 600 || _POSIX_VERSION >= 200112L\n    #define ecb_ldexpf(x,e) ldexpf ((x), (e))\n    #define ecb_frexpf(x,e) frexpf ((x), (e))\n  #else\n    #define ecb_ldexpf(x,e) (float) ldexp ((double) (x), (e))\n    #define ecb_frexpf(x,e) (float) frexp ((double) (x), (e))\n  #endif\n\n  /* convert a float to ieee single/binary32 */\n  ecb_function_ ecb_const uint32_t ecb_float_to_binary32 (float x);\n  ecb_function_ ecb_const uint32_t\n  ecb_float_to_binary32 (float x)\n  {\n    uint32_t r;\n\n    #if ECB_STDFP\n      memcpy (&r, &x, 4);\n    #else\n      /* slow emulation, works for anything but -0 */\n      uint32_t m;\n      int e;\n\n      if (x == 0e0f                    ) return 0x00000000U;\n      if (x > +3.40282346638528860e+38f) return 0x7f800000U;\n      if (x < -3.40282346638528860e+38f) return 0xff800000U;\n      if (x != x                       ) return 0x7fbfffffU;\n\n      m = ecb_frexpf (x, &e) * 0x1000000U;\n\n      r = m & 0x80000000U;\n\n      if (r)\n        m = -m;\n\n      if (e <= -126)\n        {\n          m &= 0xffffffU;\n          m >>= (-125 - e);\n          e = -126;\n        }\n\n      r |= (e + 126) << 23;\n      r |= m & 0x7fffffU;\n    #endif\n\n    return r;\n  }\n\n  /* converts an ieee single/binary32 to a float */\n  ecb_function_ ecb_const float ecb_binary32_to_float (uint32_t x);\n  ecb_function_ ecb_const float\n  ecb_binary32_to_float (uint32_t x)\n  {\n    float r;\n\n    #if ECB_STDFP\n      memcpy (&r, &x, 4);\n    #else\n      /* emulation, only works for normals and subnormals and +0 */\n      int neg = x >> 31;\n      int e = (x >> 23) & 0xffU;\n\n      x &= 0x7fffffU;\n\n      if (e)\n        x |= 0x800000U;\n      else\n        e = 1;\n\n      /* we distrust ldexpf a bit and do the 2**-24 scaling by an extra multiply */\n      r = ecb_ldexpf (x * (0.5f / 0x800000U), e - 126);\n\n      r = neg ? -r : r;\n    #endif\n\n    return r;\n  }\n\n  /* convert a double to ieee double/binary64 */\n  ecb_function_ ecb_const uint64_t ecb_double_to_binary64 (double x);\n  ecb_function_ ecb_const uint64_t\n  ecb_double_to_binary64 (double x)\n  {\n    uint64_t r;\n\n    #if ECB_STDFP\n      memcpy (&r, &x, 8);\n    #else\n      /* slow emulation, works for anything but -0 */\n      uint64_t m;\n      int e;\n\n      if (x == 0e0                     ) return 0x0000000000000000U;\n      if (x > +1.79769313486231470e+308) return 0x7ff0000000000000U;\n      if (x < -1.79769313486231470e+308) return 0xfff0000000000000U;\n      if (x != x                       ) return 0X7ff7ffffffffffffU;\n\n      m = frexp (x, &e) * 0x20000000000000U;\n\n      r = m & 0x8000000000000000;;\n\n      if (r)\n        m = -m;\n\n      if (e <= -1022)\n        {\n          m &= 0x1fffffffffffffU;\n          m >>= (-1021 - e);\n          e = -1022;\n        }\n\n      r |= ((uint64_t)(e + 1022)) << 52;\n      r |= m & 0xfffffffffffffU;\n    #endif\n\n    return r;\n  }\n\n  /* converts an ieee double/binary64 to a double */\n  ecb_function_ ecb_const double ecb_binary64_to_double (uint64_t x);\n  ecb_function_ ecb_const double\n  ecb_binary64_to_double (uint64_t x)\n  {\n    double r;\n\n    #if ECB_STDFP\n      memcpy (&r, &x, 8);\n    #else\n      /* emulation, only works for normals and subnormals and +0 */\n      int neg = x >> 63;\n      int e = (x >> 52) & 0x7ffU;\n\n      x &= 0xfffffffffffffU;\n\n      if (e)\n        x |= 0x10000000000000U;\n      else\n        e = 1;\n\n      /* we distrust ldexp a bit and do the 2**-53 scaling by an extra multiply */\n      r = ldexp (x * (0.5 / 0x10000000000000U), e - 1022);\n\n      r = neg ? -r : r;\n    #endif\n\n    return r;\n  }\n\n  /* convert a float to ieee half/binary16 */\n  ecb_function_ ecb_const uint16_t ecb_float_to_binary16 (float x);\n  ecb_function_ ecb_const uint16_t\n  ecb_float_to_binary16 (float x)\n  {\n    return ecb_binary32_to_binary16 (ecb_float_to_binary32 (x));\n  }\n\n  /* convert an ieee half/binary16 to float */\n  ecb_function_ ecb_const float ecb_binary16_to_float (uint16_t x);\n  ecb_function_ ecb_const float\n  ecb_binary16_to_float (uint16_t x)\n  {\n    return ecb_binary32_to_float (ecb_binary16_to_binary32 (x));\n  }\n\n#endif\n\n#endif\n\n/* ECB.H END */\n\n#if ECB_MEMORY_FENCE_NEEDS_PTHREADS\n/* if your architecture doesn't need memory fences, e.g. because it is\n * single-cpu/core, or if you use libev in a project that doesn't use libev\n * from multiple threads, then you can define ECB_NO_THREADS when compiling\n * libev, in which cases the memory fences become nops.\n * alternatively, you can remove this #error and link against libpthread,\n * which will then provide the memory fences.\n */\n# error \"memory fences not defined for your architecture, please report\"\n#endif\n\n#ifndef ECB_MEMORY_FENCE\n# define ECB_MEMORY_FENCE do { } while (0)\n# define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE\n# define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE\n#endif\n\n#define inline_size        ecb_inline\n\n#if EV_FEATURE_CODE\n# define inline_speed      ecb_inline\n#else\n# define inline_speed      ecb_noinline static\n#endif\n\n/*****************************************************************************/\n/* raw syscall wrappers */\n\n#if EV_NEED_SYSCALL\n\n#include <sys/syscall.h>\n\n/*\n * define some syscall wrappers for common architectures\n * this is mostly for nice looks during debugging, not performance.\n * our syscalls return < 0, not == -1, on error. which is good\n * enough for linux aio.\n * TODO: arm is also common nowadays, maybe even mips and x86\n * TODO: after implementing this, it suddenly looks like overkill, but its hard to remove...\n */\n#if __GNUC__ && __linux && ECB_AMD64 && !EV_FEATURE_CODE\n  /* the costly errno access probably kills this for size optimisation */\n\n  #define ev_syscall(nr,narg,arg1,arg2,arg3,arg4,arg5,arg6)            \\\n    ({                                                                 \\\n        long res;                                                      \\\n        register unsigned long r6 __asm__ (\"r9\" );                     \\\n        register unsigned long r5 __asm__ (\"r8\" );                     \\\n        register unsigned long r4 __asm__ (\"r10\");                     \\\n        register unsigned long r3 __asm__ (\"rdx\");                     \\\n        register unsigned long r2 __asm__ (\"rsi\");                     \\\n        register unsigned long r1 __asm__ (\"rdi\");                     \\\n        if (narg >= 6) r6 = (unsigned long)(arg6);                     \\\n        if (narg >= 5) r5 = (unsigned long)(arg5);                     \\\n        if (narg >= 4) r4 = (unsigned long)(arg4);                     \\\n        if (narg >= 3) r3 = (unsigned long)(arg3);                     \\\n        if (narg >= 2) r2 = (unsigned long)(arg2);                     \\\n        if (narg >= 1) r1 = (unsigned long)(arg1);                     \\\n        __asm__ __volatile__ (                                         \\\n          \"syscall\\n\\t\"                                                \\\n          : \"=a\" (res)                                                 \\\n          : \"0\" (nr), \"r\" (r1), \"r\" (r2), \"r\" (r3), \"r\" (r4), \"r\" (r5) \\\n          : \"cc\", \"r11\", \"cx\", \"memory\");                              \\\n        errno = -res;                                                  \\\n        res;                                                           \\\n    })\n\n#endif\n\n#ifdef ev_syscall\n  #define ev_syscall0(nr)                               ev_syscall (nr, 0,    0,    0,    0,    0,    0,   0)\n  #define ev_syscall1(nr,arg1)                          ev_syscall (nr, 1, arg1,    0,    0,    0,    0,   0)\n  #define ev_syscall2(nr,arg1,arg2)                     ev_syscall (nr, 2, arg1, arg2,    0,    0,    0,   0)\n  #define ev_syscall3(nr,arg1,arg2,arg3)                ev_syscall (nr, 3, arg1, arg2, arg3,    0,    0,   0)\n  #define ev_syscall4(nr,arg1,arg2,arg3,arg4)           ev_syscall (nr, 3, arg1, arg2, arg3, arg4,    0,   0)\n  #define ev_syscall5(nr,arg1,arg2,arg3,arg4,arg5)      ev_syscall (nr, 5, arg1, arg2, arg3, arg4, arg5,   0)\n  #define ev_syscall6(nr,arg1,arg2,arg3,arg4,arg5,arg6) ev_syscall (nr, 6, arg1, arg2, arg3, arg4, arg5,arg6)\n#else\n  #define ev_syscall0(nr)                               syscall (nr)\n  #define ev_syscall1(nr,arg1)                          syscall (nr, arg1)\n  #define ev_syscall2(nr,arg1,arg2)                     syscall (nr, arg1, arg2)\n  #define ev_syscall3(nr,arg1,arg2,arg3)                syscall (nr, arg1, arg2, arg3)\n  #define ev_syscall4(nr,arg1,arg2,arg3,arg4)           syscall (nr, arg1, arg2, arg3, arg4)\n  #define ev_syscall5(nr,arg1,arg2,arg3,arg4,arg5)      syscall (nr, arg1, arg2, arg3, arg4, arg5)\n  #define ev_syscall6(nr,arg1,arg2,arg3,arg4,arg5,arg6) syscall (nr, arg1, arg2, arg3, arg4, arg5,arg6)\n#endif\n\n#endif\n\n/*****************************************************************************/\n\n#define NUMPRI (EV_MAXPRI - EV_MINPRI + 1)\n\n#if EV_MINPRI == EV_MAXPRI\n# define ABSPRI(w) (((W)w), 0)\n#else\n# define ABSPRI(w) (((W)w)->priority - EV_MINPRI)\n#endif\n\n#define EMPTY /* required for microsofts broken pseudo-c compiler */\n\ntypedef ev_watcher *W;\ntypedef ev_watcher_list *WL;\ntypedef ev_watcher_time *WT;\n\n#define ev_active(w) ((W)(w))->active\n#define ev_at(w) ((WT)(w))->at\n\n#if EV_USE_REALTIME\n/* sig_atomic_t is used to avoid per-thread variables or locking but still */\n/* giving it a reasonably high chance of working on typical architectures */\nstatic EV_ATOMIC_T have_realtime; /* did clock_gettime (CLOCK_REALTIME) work? */\n#endif\n\n#if EV_USE_MONOTONIC\nstatic EV_ATOMIC_T have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work? */\n#endif\n\n#ifndef EV_FD_TO_WIN32_HANDLE\n# define EV_FD_TO_WIN32_HANDLE(fd) _get_osfhandle (fd)\n#endif\n#ifndef EV_WIN32_HANDLE_TO_FD\n# define EV_WIN32_HANDLE_TO_FD(handle) _open_osfhandle (handle, 0)\n#endif\n#ifndef EV_WIN32_CLOSE_FD\n# define EV_WIN32_CLOSE_FD(fd) close (fd)\n#endif\n\n#ifdef _WIN32\n# include \"ev_win32.c\"\n#endif\n\n/*****************************************************************************/\n\n#if EV_USE_LINUXAIO\n# include <linux/aio_abi.h> /* probably only needed for aio_context_t */\n#endif\n\n/* define a suitable floor function (only used by periodics atm) */\n\n#if EV_USE_FLOOR\n# include <math.h>\n# define ev_floor(v) floor (v)\n#else\n\n#include <float.h>\n\n/* a floor() replacement function, should be independent of ev_tstamp type */\necb_noinline\nstatic ev_tstamp\nev_floor (ev_tstamp v)\n{\n  /* the choice of shift factor is not terribly important */\n#if FLT_RADIX != 2 /* assume FLT_RADIX == 10 */\n  const ev_tstamp shift = sizeof (unsigned long) >= 8 ? 10000000000000000000. : 1000000000.;\n#else\n  const ev_tstamp shift = sizeof (unsigned long) >= 8 ? 18446744073709551616. : 4294967296.;\n#endif\n\n  /* special treatment for negative arguments */\n  if (ecb_expect_false (v < 0.))\n    {\n      ev_tstamp f = -ev_floor (-v);\n\n      return f - (f == v ? 0 : 1);\n    }\n\n  /* argument too large for an unsigned long? then reduce it */\n  if (ecb_expect_false (v >= shift))\n    {\n      ev_tstamp f;\n\n      if (v == v - 1.)\n        return v; /* very large numbers are assumed to be integer */\n\n      f = shift * ev_floor (v * (1. / shift));\n      return f + ev_floor (v - f);\n    }\n\n  /* fits into an unsigned long */\n  return (unsigned long)v;\n}\n\n#endif\n\n/*****************************************************************************/\n\n#ifdef __linux\n# include <sys/utsname.h>\n#endif\n\necb_noinline ecb_cold\nstatic unsigned int\nev_linux_version (void)\n{\n#ifdef __linux\n  unsigned int v = 0;\n  struct utsname buf;\n  int i;\n  char *p = buf.release;\n\n  if (uname (&buf))\n    return 0;\n\n  for (i = 3+1; --i; )\n    {\n      unsigned int c = 0;\n\n      for (;;)\n        {\n          if (*p >= '0' && *p <= '9')\n            c = c * 10 + *p++ - '0';\n          else\n            {\n              p += *p == '.';\n              break;\n            }\n        }\n\n      v = (v << 8) | c;\n    }\n\n  return v;\n#else\n  return 0;\n#endif\n}\n\n/*****************************************************************************/\n\n#if EV_AVOID_STDIO\necb_noinline ecb_cold\nstatic void\nev_printerr (const char *msg)\n{\n  write (STDERR_FILENO, msg, strlen (msg));\n}\n#endif\n\nstatic void (*syserr_cb)(const char *msg) EV_NOEXCEPT;\n\necb_cold\nvoid\nev_set_syserr_cb (void (*cb)(const char *msg) EV_NOEXCEPT) EV_NOEXCEPT\n{\n  syserr_cb = cb;\n}\n\necb_noinline ecb_cold\nstatic void\nev_syserr (const char *msg)\n{\n  if (!msg)\n    msg = \"(libev) system error\";\n\n  if (syserr_cb)\n    syserr_cb (msg);\n  else\n    {\n#if EV_AVOID_STDIO\n      ev_printerr (msg);\n      ev_printerr (\": \");\n      ev_printerr (strerror (errno));\n      ev_printerr (\"\\n\");\n#else\n      perror (msg);\n#endif\n      abort ();\n    }\n}\n\nstatic void *\nev_realloc_emul (void *ptr, long size) EV_NOEXCEPT\n{\n  /* some systems, notably openbsd and darwin, fail to properly\n   * implement realloc (x, 0) (as required by both ansi c-89 and\n   * the single unix specification, so work around them here.\n   * recently, also (at least) fedora and debian started breaking it,\n   * despite documenting it otherwise.\n   */\n\n  if (size)\n    return realloc (ptr, size);\n\n  free (ptr);\n  return 0;\n}\n\nstatic void *(*alloc)(void *ptr, long size) EV_NOEXCEPT = ev_realloc_emul;\n\necb_cold\nvoid\nev_set_allocator (void *(*cb)(void *ptr, long size) EV_NOEXCEPT) EV_NOEXCEPT\n{\n  alloc = cb;\n}\n\ninline_speed void *\nev_realloc (void *ptr, long size)\n{\n  ptr = alloc (ptr, size);\n\n  if (!ptr && size)\n    {\n#if EV_AVOID_STDIO\n      ev_printerr (\"(libev) memory allocation failed, aborting.\\n\");\n#else\n      fprintf (stderr, \"(libev) cannot allocate %ld bytes, aborting.\", size);\n#endif\n      abort ();\n    }\n\n  return ptr;\n}\n\n#define ev_malloc(size) ev_realloc (0, (size))\n#define ev_free(ptr)    ev_realloc ((ptr), 0)\n\n/*****************************************************************************/\n\n/* set in reify when reification needed */\n#define EV_ANFD_REIFY 1\n\n/* file descriptor info structure */\ntypedef struct\n{\n  WL head;\n  unsigned char events; /* the events watched for */\n  unsigned char reify;  /* flag set when this ANFD needs reification (EV_ANFD_REIFY, EV__IOFDSET) */\n  unsigned char emask;  /* some backends store the actual kernel mask in here */\n  unsigned char eflags; /* flags field for use by backends */\n#if EV_USE_EPOLL\n  unsigned int egen;    /* generation counter to counter epoll bugs */\n#endif\n#if EV_SELECT_IS_WINSOCKET || EV_USE_IOCP\n  SOCKET handle;\n#endif\n#if EV_USE_IOCP\n  OVERLAPPED or, ow;\n#endif\n} ANFD;\n\n/* stores the pending event set for a given watcher */\ntypedef struct\n{\n  W w;\n  int events; /* the pending event set for the given watcher */\n} ANPENDING;\n\n#if EV_USE_INOTIFY\n/* hash table entry per inotify-id */\ntypedef struct\n{\n  WL head;\n} ANFS;\n#endif\n\n/* Heap Entry */\n#if EV_HEAP_CACHE_AT\n  /* a heap element */\n  typedef struct {\n    ev_tstamp at;\n    WT w;\n  } ANHE;\n\n  #define ANHE_w(he)        (he).w     /* access watcher, read-write */\n  #define ANHE_at(he)       (he).at    /* access cached at, read-only */\n  #define ANHE_at_cache(he) (he).at = (he).w->at /* update at from watcher */\n#else\n  /* a heap element */\n  typedef WT ANHE;\n\n  #define ANHE_w(he)        (he)\n  #define ANHE_at(he)       (he)->at\n  #define ANHE_at_cache(he)\n#endif\n\n#if EV_MULTIPLICITY\n\n  struct ev_loop\n  {\n    ev_tstamp ev_rt_now;\n    #define ev_rt_now ((loop)->ev_rt_now)\n    #define VAR(name,decl) decl;\n      #include \"ev_vars.h\"\n    #undef VAR\n  };\n  #include \"ev_wrap.h\"\n\n  static struct ev_loop default_loop_struct;\n  EV_API_DECL struct ev_loop *ev_default_loop_ptr = 0; /* needs to be initialised to make it a definition despite extern */\n\n#else\n\n  EV_API_DECL ev_tstamp ev_rt_now = EV_TS_CONST (0.); /* needs to be initialised to make it a definition despite extern */\n  #define VAR(name,decl) static decl;\n    #include \"ev_vars.h\"\n  #undef VAR\n\n  static int ev_default_loop_ptr;\n\n#endif\n\n#if EV_FEATURE_API\n# define EV_RELEASE_CB if (ecb_expect_false (release_cb)) release_cb (EV_A)\n# define EV_ACQUIRE_CB if (ecb_expect_false (acquire_cb)) acquire_cb (EV_A)\n# define EV_INVOKE_PENDING invoke_cb (EV_A)\n#else\n# define EV_RELEASE_CB (void)0\n# define EV_ACQUIRE_CB (void)0\n# define EV_INVOKE_PENDING ev_invoke_pending (EV_A)\n#endif\n\n#define EVBREAK_RECURSE 0x80\n\n/*****************************************************************************/\n\n#ifndef EV_HAVE_EV_TIME\nev_tstamp\nev_time (void) EV_NOEXCEPT\n{\n#if EV_USE_REALTIME\n  if (ecb_expect_true (have_realtime))\n    {\n      struct timespec ts;\n      clock_gettime (CLOCK_REALTIME, &ts);\n      return EV_TS_GET (ts);\n    }\n#endif\n\n  {\n    struct timeval tv;\n    gettimeofday (&tv, 0);\n    return EV_TV_GET (tv);\n  }\n}\n#endif\n\ninline_size ev_tstamp\nget_clock (void)\n{\n#if EV_USE_MONOTONIC\n  if (ecb_expect_true (have_monotonic))\n    {\n      struct timespec ts;\n      clock_gettime (CLOCK_MONOTONIC, &ts);\n      return EV_TS_GET (ts);\n    }\n#endif\n\n  return ev_time ();\n}\n\n#if EV_MULTIPLICITY\nev_tstamp\nev_now (EV_P) EV_NOEXCEPT\n{\n  return ev_rt_now;\n}\n#endif\n\nvoid\nev_sleep (ev_tstamp delay) EV_NOEXCEPT\n{\n  if (delay > EV_TS_CONST (0.))\n    {\n#if EV_USE_NANOSLEEP\n      struct timespec ts;\n\n      EV_TS_SET (ts, delay);\n      nanosleep (&ts, 0);\n#elif defined _WIN32\n      /* maybe this should round up, as ms is very low resolution */\n      /* compared to select (µs) or nanosleep (ns) */\n      Sleep ((unsigned long)(EV_TS_TO_MSEC (delay)));\n#else\n      struct timeval tv;\n\n      /* here we rely on sys/time.h + sys/types.h + unistd.h providing select */\n      /* something not guaranteed by newer posix versions, but guaranteed */\n      /* by older ones */\n      EV_TV_SET (tv, delay);\n      select (0, 0, 0, 0, &tv);\n#endif\n    }\n}\n\n/*****************************************************************************/\n\n#define MALLOC_ROUND 4096 /* prefer to allocate in chunks of this size, must be 2**n and >> 4 longs */\n\n/* find a suitable new size for the given array, */\n/* hopefully by rounding to a nice-to-malloc size */\ninline_size int\narray_nextsize (int elem, int cur, int cnt)\n{\n  int ncur = cur + 1;\n\n  do\n    ncur <<= 1;\n  while (cnt > ncur);\n\n  /* if size is large, round to MALLOC_ROUND - 4 * longs to accommodate malloc overhead */\n  if (elem * ncur > MALLOC_ROUND - (int)sizeof (void *) * 4)\n    {\n      ncur *= elem;\n      ncur = (ncur + elem + (MALLOC_ROUND - 1) + sizeof (void *) * 4) & ~(MALLOC_ROUND - 1);\n      ncur = ncur - sizeof (void *) * 4;\n      ncur /= elem;\n    }\n\n  return ncur;\n}\n\necb_noinline ecb_cold\nstatic void *\narray_realloc (int elem, void *base, int *cur, int cnt)\n{\n  *cur = array_nextsize (elem, *cur, cnt);\n  return ev_realloc (base, elem * *cur);\n}\n\n#define array_needsize_noinit(base,offset,count)\n\n#define array_needsize_zerofill(base,offset,count)\t\\\n  memset ((void *)(base + offset), 0, sizeof (*(base)) * (count))\n\n#define array_needsize(type,base,cur,cnt,init)\t\t\t\\\n  if (ecb_expect_false ((cnt) > (cur)))\t\t\t\t\\\n    {\t\t\t\t\t\t\t\t\\\n      ecb_unused int ocur_ = (cur);\t\t\t\t\\\n      (base) = (type *)array_realloc\t\t\t\t\\\n         (sizeof (type), (base), &(cur), (cnt));\t\t\\\n      init ((base), ocur_, ((cur) - ocur_));\t\t\t\\\n    }\n\n#if 0\n#define array_slim(type,stem)\t\t\t\t\t\\\n  if (stem ## max < array_roundsize (stem ## cnt >> 2))\t\t\\\n    {\t\t\t\t\t\t\t\t\\\n      stem ## max = array_roundsize (stem ## cnt >> 1);\t\t\\\n      base = (type *)ev_realloc (base, sizeof (type) * (stem ## max));\\\n      fprintf (stderr, \"slimmed down \" # stem \" to %d\\n\", stem ## max);/*D*/\\\n    }\n#endif\n\n#define array_free(stem, idx) \\\n  ev_free (stem ## s idx); stem ## cnt idx = stem ## max idx = 0; stem ## s idx = 0\n\n/*****************************************************************************/\n\n/* dummy callback for pending events */\necb_noinline\nstatic void\npendingcb (EV_P_ ev_prepare *w, int revents)\n{\n}\n\necb_noinline\nvoid\nev_feed_event (EV_P_ void *w, int revents) EV_NOEXCEPT\n{\n  W w_ = (W)w;\n  int pri = ABSPRI (w_);\n\n  if (ecb_expect_false (w_->pending))\n    pendings [pri][w_->pending - 1].events |= revents;\n  else\n    {\n      w_->pending = ++pendingcnt [pri];\n      array_needsize (ANPENDING, pendings [pri], pendingmax [pri], w_->pending, array_needsize_noinit);\n      pendings [pri][w_->pending - 1].w      = w_;\n      pendings [pri][w_->pending - 1].events = revents;\n    }\n\n  pendingpri = NUMPRI - 1;\n}\n\ninline_speed void\nfeed_reverse (EV_P_ W w)\n{\n  array_needsize (W, rfeeds, rfeedmax, rfeedcnt + 1, array_needsize_noinit);\n  rfeeds [rfeedcnt++] = w;\n}\n\ninline_size void\nfeed_reverse_done (EV_P_ int revents)\n{\n  do\n    ev_feed_event (EV_A_ rfeeds [--rfeedcnt], revents);\n  while (rfeedcnt);\n}\n\ninline_speed void\nqueue_events (EV_P_ W *events, int eventcnt, int type)\n{\n  int i;\n\n  for (i = 0; i < eventcnt; ++i)\n    ev_feed_event (EV_A_ events [i], type);\n}\n\n/*****************************************************************************/\n\ninline_speed void\nfd_event_nocheck (EV_P_ int fd, int revents)\n{\n  ANFD *anfd = anfds + fd;\n  ev_io *w;\n\n  for (w = (ev_io *)anfd->head; w; w = (ev_io *)((WL)w)->next)\n    {\n      int ev = w->events & revents;\n\n      if (ev)\n        ev_feed_event (EV_A_ (W)w, ev);\n    }\n}\n\n/* do not submit kernel events for fds that have reify set */\n/* because that means they changed while we were polling for new events */\ninline_speed void\nfd_event (EV_P_ int fd, int revents)\n{\n  ANFD *anfd = anfds + fd;\n\n  if (ecb_expect_true (!anfd->reify))\n    fd_event_nocheck (EV_A_ fd, revents);\n}\n\nvoid\nev_feed_fd_event (EV_P_ int fd, int revents) EV_NOEXCEPT\n{\n  if (fd >= 0 && fd < anfdmax)\n    fd_event_nocheck (EV_A_ fd, revents);\n}\n\n/* make sure the external fd watch events are in-sync */\n/* with the kernel/libev internal state */\ninline_size void\nfd_reify (EV_P)\n{\n  int i;\n\n  /* most backends do not modify the fdchanges list in backend_modfiy.\n   * except io_uring, which has fixed-size buffers which might force us\n   * to handle events in backend_modify, causing fdchanges to be amended,\n   * which could result in an endless loop.\n   * to avoid this, we do not dynamically handle fds that were added\n   * during fd_reify. that means that for those backends, fdchangecnt\n   * might be non-zero during poll, which must cause them to not block.\n   * to not put too much of a burden on other backends, this detail\n   * needs to be handled in the backend.\n   */\n  int changecnt = fdchangecnt;\n\n#if EV_SELECT_IS_WINSOCKET || EV_USE_IOCP\n  for (i = 0; i < changecnt; ++i)\n    {\n      int fd = fdchanges [i];\n      ANFD *anfd = anfds + fd;\n\n      if (anfd->reify & EV__IOFDSET && anfd->head)\n        {\n          SOCKET handle = EV_FD_TO_WIN32_HANDLE (fd);\n\n          if (handle != anfd->handle)\n            {\n              unsigned long arg;\n\n              assert ((\"libev: only socket fds supported in this configuration\", ioctlsocket (handle, FIONREAD, &arg) == 0));\n\n              /* handle changed, but fd didn't - we need to do it in two steps */\n              backend_modify (EV_A_ fd, anfd->events, 0);\n              anfd->events = 0;\n              anfd->handle = handle;\n            }\n        }\n    }\n#endif\n\n  for (i = 0; i < changecnt; ++i)\n    {\n      int fd = fdchanges [i];\n      ANFD *anfd = anfds + fd;\n      ev_io *w;\n\n      unsigned char o_events = anfd->events;\n      unsigned char o_reify  = anfd->reify;\n\n      anfd->reify = 0;\n\n      /*if (ecb_expect_true (o_reify & EV_ANFD_REIFY)) probably a deoptimisation */\n        {\n          anfd->events = 0;\n\n          for (w = (ev_io *)anfd->head; w; w = (ev_io *)((WL)w)->next)\n            anfd->events |= (unsigned char)w->events;\n\n          if (o_events != anfd->events)\n            o_reify = EV__IOFDSET; /* actually |= */\n        }\n\n      if (o_reify & EV__IOFDSET)\n        backend_modify (EV_A_ fd, o_events, anfd->events);\n    }\n\n  /* normally, fdchangecnt hasn't changed. if it has, then new fds have been added.\n   * this is a rare case (see beginning comment in this function), so we copy them to the\n   * front and hope the backend handles this case.\n   */\n  if (ecb_expect_false (fdchangecnt != changecnt))\n    memmove (fdchanges, fdchanges + changecnt, (fdchangecnt - changecnt) * sizeof (*fdchanges));\n\n  fdchangecnt -= changecnt;\n}\n\n/* something about the given fd changed */\ninline_size\nvoid\nfd_change (EV_P_ int fd, int flags)\n{\n  unsigned char reify = anfds [fd].reify;\n  anfds [fd].reify = reify | flags;\n\n  if (ecb_expect_true (!reify))\n    {\n      ++fdchangecnt;\n      array_needsize (int, fdchanges, fdchangemax, fdchangecnt, array_needsize_noinit);\n      fdchanges [fdchangecnt - 1] = fd;\n    }\n}\n\n/* the given fd is invalid/unusable, so make sure it doesn't hurt us anymore */\ninline_speed ecb_cold void\nfd_kill (EV_P_ int fd)\n{\n  ev_io *w;\n\n  while ((w = (ev_io *)anfds [fd].head))\n    {\n      ev_io_stop (EV_A_ w);\n      ev_feed_event (EV_A_ (W)w, EV_ERROR | EV_READ | EV_WRITE);\n    }\n}\n\n/* check whether the given fd is actually valid, for error recovery */\ninline_size ecb_cold int\nfd_valid (int fd)\n{\n#ifdef _WIN32\n  return EV_FD_TO_WIN32_HANDLE (fd) != -1;\n#else\n  return fcntl (fd, F_GETFD) != -1;\n#endif\n}\n\n/* called on EBADF to verify fds */\necb_noinline ecb_cold\nstatic void\nfd_ebadf (EV_P)\n{\n  int fd;\n\n  for (fd = 0; fd < anfdmax; ++fd)\n    if (anfds [fd].events)\n      if (!fd_valid (fd) && errno == EBADF)\n        fd_kill (EV_A_ fd);\n}\n\n/* called on ENOMEM in select/poll to kill some fds and retry */\necb_noinline ecb_cold\nstatic void\nfd_enomem (EV_P)\n{\n  int fd;\n\n  for (fd = anfdmax; fd--; )\n    if (anfds [fd].events)\n      {\n        fd_kill (EV_A_ fd);\n        break;\n      }\n}\n\n/* usually called after fork if backend needs to re-arm all fds from scratch */\necb_noinline\nstatic void\nfd_rearm_all (EV_P)\n{\n  int fd;\n\n  for (fd = 0; fd < anfdmax; ++fd)\n    if (anfds [fd].events)\n      {\n        anfds [fd].events = 0;\n        anfds [fd].emask  = 0;\n        fd_change (EV_A_ fd, EV__IOFDSET | EV_ANFD_REIFY);\n      }\n}\n\n/* used to prepare libev internal fd's */\n/* this is not fork-safe */\ninline_speed void\nfd_intern (int fd)\n{\n#ifdef _WIN32\n  unsigned long arg = 1;\n  ioctlsocket (EV_FD_TO_WIN32_HANDLE (fd), FIONBIO, &arg);\n#else\n  fcntl (fd, F_SETFD, FD_CLOEXEC);\n  fcntl (fd, F_SETFL, O_NONBLOCK);\n#endif\n}\n\n/*****************************************************************************/\n\n/*\n * the heap functions want a real array index. array index 0 is guaranteed to not\n * be in-use at any time. the first heap entry is at array [HEAP0]. DHEAP gives\n * the branching factor of the d-tree.\n */\n\n/*\n * at the moment we allow libev the luxury of two heaps,\n * a small-code-size 2-heap one and a ~1.5kb larger 4-heap\n * which is more cache-efficient.\n * the difference is about 5% with 50000+ watchers.\n */\n#if EV_USE_4HEAP\n\n#define DHEAP 4\n#define HEAP0 (DHEAP - 1) /* index of first element in heap */\n#define HPARENT(k) ((((k) - HEAP0 - 1) / DHEAP) + HEAP0)\n#define UPHEAP_DONE(p,k) ((p) == (k))\n\n/* away from the root */\ninline_speed void\ndownheap (ANHE *heap, int N, int k)\n{\n  ANHE he = heap [k];\n  ANHE *E = heap + N + HEAP0;\n\n  for (;;)\n    {\n      ev_tstamp minat;\n      ANHE *minpos;\n      ANHE *pos = heap + DHEAP * (k - HEAP0) + HEAP0 + 1;\n\n      /* find minimum child */\n      if (ecb_expect_true (pos + DHEAP - 1 < E))\n        {\n          /* fast path */                               (minpos = pos + 0), (minat = ANHE_at (*minpos));\n          if (               minat > ANHE_at (pos [1])) (minpos = pos + 1), (minat = ANHE_at (*minpos));\n          if (               minat > ANHE_at (pos [2])) (minpos = pos + 2), (minat = ANHE_at (*minpos));\n          if (               minat > ANHE_at (pos [3])) (minpos = pos + 3), (minat = ANHE_at (*minpos));\n        }\n      else if (pos < E)\n        {\n          /* slow path */                               (minpos = pos + 0), (minat = ANHE_at (*minpos));\n          if (pos + 1 < E && minat > ANHE_at (pos [1])) (minpos = pos + 1), (minat = ANHE_at (*minpos));\n          if (pos + 2 < E && minat > ANHE_at (pos [2])) (minpos = pos + 2), (minat = ANHE_at (*minpos));\n          if (pos + 3 < E && minat > ANHE_at (pos [3])) (minpos = pos + 3), (minat = ANHE_at (*minpos));\n        }\n      else\n        break;\n\n      if (ANHE_at (he) <= minat)\n        break;\n\n      heap [k] = *minpos;\n      ev_active (ANHE_w (*minpos)) = k;\n\n      k = minpos - heap;\n    }\n\n  heap [k] = he;\n  ev_active (ANHE_w (he)) = k;\n}\n\n#else /* not 4HEAP */\n\n#define HEAP0 1\n#define HPARENT(k) ((k) >> 1)\n#define UPHEAP_DONE(p,k) (!(p))\n\n/* away from the root */\ninline_speed void\ndownheap (ANHE *heap, int N, int k)\n{\n  ANHE he = heap [k];\n\n  for (;;)\n    {\n      int c = k << 1;\n\n      if (c >= N + HEAP0)\n        break;\n\n      c += c + 1 < N + HEAP0 && ANHE_at (heap [c]) > ANHE_at (heap [c + 1])\n           ? 1 : 0;\n\n      if (ANHE_at (he) <= ANHE_at (heap [c]))\n        break;\n\n      heap [k] = heap [c];\n      ev_active (ANHE_w (heap [k])) = k;\n      \n      k = c;\n    }\n\n  heap [k] = he;\n  ev_active (ANHE_w (he)) = k;\n}\n#endif\n\n/* towards the root */\ninline_speed void\nupheap (ANHE *heap, int k)\n{\n  ANHE he = heap [k];\n\n  for (;;)\n    {\n      int p = HPARENT (k);\n\n      if (UPHEAP_DONE (p, k) || ANHE_at (heap [p]) <= ANHE_at (he))\n        break;\n\n      heap [k] = heap [p];\n      ev_active (ANHE_w (heap [k])) = k;\n      k = p;\n    }\n\n  heap [k] = he;\n  ev_active (ANHE_w (he)) = k;\n}\n\n/* move an element suitably so it is in a correct place */\ninline_size void\nadjustheap (ANHE *heap, int N, int k)\n{\n  if (k > HEAP0 && ANHE_at (heap [k]) <= ANHE_at (heap [HPARENT (k)]))\n    upheap (heap, k);\n  else\n    downheap (heap, N, k);\n}\n\n/* rebuild the heap: this function is used only once and executed rarely */\ninline_size void\nreheap (ANHE *heap, int N)\n{\n  int i;\n\n  /* we don't use floyds algorithm, upheap is simpler and is more cache-efficient */\n  /* also, this is easy to implement and correct for both 2-heaps and 4-heaps */\n  for (i = 0; i < N; ++i)\n    upheap (heap, i + HEAP0);\n}\n\n/*****************************************************************************/\n\n/* associate signal watchers to a signal */\ntypedef struct\n{\n  EV_ATOMIC_T pending;\n#if EV_MULTIPLICITY\n  EV_P;\n#endif\n  WL head;\n} ANSIG;\n\nstatic ANSIG signals [EV_NSIG - 1];\n\n/*****************************************************************************/\n\n#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE\n\necb_noinline ecb_cold\nstatic void\nevpipe_init (EV_P)\n{\n  if (!ev_is_active (&pipe_w))\n    {\n      int fds [2];\n\n# if EV_USE_EVENTFD\n      fds [0] = -1;\n      fds [1] = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC);\n      if (fds [1] < 0 && errno == EINVAL)\n        fds [1] = eventfd (0, 0);\n\n      if (fds [1] < 0)\n# endif\n        {\n          while (pipe (fds))\n            ev_syserr (\"(libev) error creating signal/async pipe\");\n\n          fd_intern (fds [0]);\n        }\n\n      evpipe [0] = fds [0];\n\n      if (evpipe [1] < 0)\n        evpipe [1] = fds [1]; /* first call, set write fd */\n      else\n        {\n          /* on subsequent calls, do not change evpipe [1] */\n          /* so that evpipe_write can always rely on its value. */\n          /* this branch does not do anything sensible on windows, */\n          /* so must not be executed on windows */\n\n          dup2 (fds [1], evpipe [1]);\n          close (fds [1]);\n        }\n\n      fd_intern (evpipe [1]);\n\n      ev_io_set (&pipe_w, evpipe [0] < 0 ? evpipe [1] : evpipe [0], EV_READ);\n      ev_io_start (EV_A_ &pipe_w);\n      ev_unref (EV_A); /* watcher should not keep loop alive */\n    }\n}\n\ninline_speed void\nevpipe_write (EV_P_ EV_ATOMIC_T *flag)\n{\n  ECB_MEMORY_FENCE; /* push out the write before this function was called, acquire flag */\n\n  if (ecb_expect_true (*flag))\n    return;\n\n  *flag = 1;\n  ECB_MEMORY_FENCE_RELEASE; /* make sure flag is visible before the wakeup */\n\n  pipe_write_skipped = 1;\n\n  ECB_MEMORY_FENCE; /* make sure pipe_write_skipped is visible before we check pipe_write_wanted */\n\n  if (pipe_write_wanted)\n    {\n      int old_errno;\n\n      pipe_write_skipped = 0;\n      ECB_MEMORY_FENCE_RELEASE;\n\n      old_errno = errno; /* save errno because write will clobber it */\n\n#if EV_USE_EVENTFD\n      if (evpipe [0] < 0)\n        {\n          uint64_t counter = 1;\n          write (evpipe [1], &counter, sizeof (uint64_t));\n        }\n      else\n#endif\n        {\n#ifdef _WIN32\n          WSABUF buf;\n          DWORD sent;\n          buf.buf = (char *)&buf;\n          buf.len = 1;\n          WSASend (EV_FD_TO_WIN32_HANDLE (evpipe [1]), &buf, 1, &sent, 0, 0, 0);\n#else\n          write (evpipe [1], &(evpipe [1]), 1);\n#endif\n        }\n\n      errno = old_errno;\n    }\n}\n\n/* called whenever the libev signal pipe */\n/* got some events (signal, async) */\nstatic void\npipecb (EV_P_ ev_io *iow, int revents)\n{\n  int i;\n\n  if (revents & EV_READ)\n    {\n#if EV_USE_EVENTFD\n      if (evpipe [0] < 0)\n        {\n          uint64_t counter;\n          read (evpipe [1], &counter, sizeof (uint64_t));\n        }\n      else\n#endif\n        {\n          char dummy[4];\n#ifdef _WIN32\n          WSABUF buf;\n          DWORD recvd;\n          DWORD flags = 0;\n          buf.buf = dummy;\n          buf.len = sizeof (dummy);\n          WSARecv (EV_FD_TO_WIN32_HANDLE (evpipe [0]), &buf, 1, &recvd, &flags, 0, 0);\n#else\n          read (evpipe [0], &dummy, sizeof (dummy));\n#endif\n        }\n    }\n\n  pipe_write_skipped = 0;\n\n  ECB_MEMORY_FENCE; /* push out skipped, acquire flags */\n\n#if EV_SIGNAL_ENABLE\n  if (sig_pending)\n    {\n      sig_pending = 0;\n\n      ECB_MEMORY_FENCE;\n\n      for (i = EV_NSIG - 1; i--; )\n        if (ecb_expect_false (signals [i].pending))\n          ev_feed_signal_event (EV_A_ i + 1);\n    }\n#endif\n\n#if EV_ASYNC_ENABLE\n  if (async_pending)\n    {\n      async_pending = 0;\n\n      ECB_MEMORY_FENCE;\n\n      for (i = asynccnt; i--; )\n        if (asyncs [i]->sent)\n          {\n            asyncs [i]->sent = 0;\n            ECB_MEMORY_FENCE_RELEASE;\n            ev_feed_event (EV_A_ asyncs [i], EV_ASYNC);\n          }\n    }\n#endif\n}\n\n/*****************************************************************************/\n\nvoid\nev_feed_signal (int signum) EV_NOEXCEPT\n{\n#if EV_MULTIPLICITY\n  EV_P;\n  ECB_MEMORY_FENCE_ACQUIRE;\n  EV_A = signals [signum - 1].loop;\n\n  if (!EV_A)\n    return;\n#endif\n\n  signals [signum - 1].pending = 1;\n  evpipe_write (EV_A_ &sig_pending);\n}\n\nstatic void\nev_sighandler (int signum)\n{\n#ifdef _WIN32\n  signal (signum, ev_sighandler);\n#endif\n\n  ev_feed_signal (signum);\n}\n\necb_noinline\nvoid\nev_feed_signal_event (EV_P_ int signum) EV_NOEXCEPT\n{\n  WL w;\n\n  if (ecb_expect_false (signum <= 0 || signum >= EV_NSIG))\n    return;\n\n  --signum;\n\n#if EV_MULTIPLICITY\n  /* it is permissible to try to feed a signal to the wrong loop */\n  /* or, likely more useful, feeding a signal nobody is waiting for */\n\n  if (ecb_expect_false (signals [signum].loop != EV_A))\n    return;\n#endif\n\n  signals [signum].pending = 0;\n  ECB_MEMORY_FENCE_RELEASE;\n\n  for (w = signals [signum].head; w; w = w->next)\n    ev_feed_event (EV_A_ (W)w, EV_SIGNAL);\n}\n\n#if EV_USE_SIGNALFD\nstatic void\nsigfdcb (EV_P_ ev_io *iow, int revents)\n{\n  struct signalfd_siginfo si[2], *sip; /* these structs are big */\n\n  for (;;)\n    {\n      ssize_t res = read (sigfd, si, sizeof (si));\n\n      /* not ISO-C, as res might be -1, but works with SuS */\n      for (sip = si; (char *)sip < (char *)si + res; ++sip)\n        ev_feed_signal_event (EV_A_ sip->ssi_signo);\n\n      if (res < (ssize_t)sizeof (si))\n        break;\n    }\n}\n#endif\n\n#endif\n\n/*****************************************************************************/\n\n#if EV_CHILD_ENABLE\nstatic WL childs [EV_PID_HASHSIZE];\n\nstatic ev_signal childev;\n\n#ifndef WIFCONTINUED\n# define WIFCONTINUED(status) 0\n#endif\n\n/* handle a single child status event */\ninline_speed void\nchild_reap (EV_P_ int chain, int pid, int status)\n{\n  ev_child *w;\n  int traced = WIFSTOPPED (status) || WIFCONTINUED (status);\n\n  for (w = (ev_child *)childs [chain & ((EV_PID_HASHSIZE) - 1)]; w; w = (ev_child *)((WL)w)->next)\n    {\n      if ((w->pid == pid || !w->pid)\n          && (!traced || (w->flags & 1)))\n        {\n          ev_set_priority (w, EV_MAXPRI); /* need to do it *now*, this *must* be the same prio as the signal watcher itself */\n          w->rpid    = pid;\n          w->rstatus = status;\n          ev_feed_event (EV_A_ (W)w, EV_CHILD);\n        }\n    }\n}\n\n#ifndef WCONTINUED\n# define WCONTINUED 0\n#endif\n\n/* called on sigchld etc., calls waitpid */\nstatic void\nchildcb (EV_P_ ev_signal *sw, int revents)\n{\n  int pid, status;\n\n  /* some systems define WCONTINUED but then fail to support it (linux 2.4) */\n  if (0 >= (pid = waitpid (-1, &status, WNOHANG | WUNTRACED | WCONTINUED)))\n    if (!WCONTINUED\n        || errno != EINVAL\n        || 0 >= (pid = waitpid (-1, &status, WNOHANG | WUNTRACED)))\n      return;\n\n  /* make sure we are called again until all children have been reaped */\n  /* we need to do it this way so that the callback gets called before we continue */\n  ev_feed_event (EV_A_ (W)sw, EV_SIGNAL);\n\n  child_reap (EV_A_ pid, pid, status);\n  if ((EV_PID_HASHSIZE) > 1)\n    child_reap (EV_A_ 0, pid, status); /* this might trigger a watcher twice, but feed_event catches that */\n}\n\n#endif\n\n/*****************************************************************************/\n\n#if EV_USE_TIMERFD\n\nstatic void periodics_reschedule (EV_P);\n\nstatic void\ntimerfdcb (EV_P_ ev_io *iow, int revents)\n{\n  struct itimerspec its = { 0 };\n\n  its.it_value.tv_sec = ev_rt_now + (int)MAX_BLOCKTIME2;\n  timerfd_settime (timerfd, TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &its, 0);\n\n  ev_rt_now = ev_time ();\n  /* periodics_reschedule only needs ev_rt_now */\n  /* but maybe in the future we want the full treatment. */\n  /*\n  now_floor = EV_TS_CONST (0.);\n  time_update (EV_A_ EV_TSTAMP_HUGE);\n  */\n#if EV_PERIODIC_ENABLE\n  periodics_reschedule (EV_A);\n#endif\n}\n\necb_noinline ecb_cold\nstatic void\nevtimerfd_init (EV_P)\n{\n  if (!ev_is_active (&timerfd_w))\n    {\n      timerfd = timerfd_create (CLOCK_REALTIME, TFD_NONBLOCK | TFD_CLOEXEC);\n\n      if (timerfd >= 0)\n        {\n          fd_intern (timerfd); /* just to be sure */\n\n          ev_io_init (&timerfd_w, timerfdcb, timerfd, EV_READ);\n          ev_set_priority (&timerfd_w, EV_MINPRI);\n          ev_io_start (EV_A_ &timerfd_w);\n          ev_unref (EV_A); /* watcher should not keep loop alive */\n\n          /* (re-) arm timer */\n          timerfdcb (EV_A_ 0, 0);\n        }\n    }\n}\n\n#endif\n\n/*****************************************************************************/\n\n#if EV_USE_IOCP\n# include \"ev_iocp.c\"\n#endif\n#if EV_USE_PORT\n# include \"ev_port.c\"\n#endif\n#if EV_USE_KQUEUE\n# include \"ev_kqueue.c\"\n#endif\n#if EV_USE_EPOLL\n# include \"ev_epoll.c\"\n#endif\n#if EV_USE_LINUXAIO\n# include \"ev_linuxaio.c\"\n#endif\n#if EV_USE_IOURING\n# include \"ev_iouring.c\"\n#endif\n#if EV_USE_POLL\n# include \"ev_poll.c\"\n#endif\n#if EV_USE_SELECT\n# include \"ev_select.c\"\n#endif\n\necb_cold int\nev_version_major (void) EV_NOEXCEPT\n{\n  return EV_VERSION_MAJOR;\n}\n\necb_cold int\nev_version_minor (void) EV_NOEXCEPT\n{\n  return EV_VERSION_MINOR;\n}\n\n/* return true if we are running with elevated privileges and should ignore env variables */\ninline_size ecb_cold int\nenable_secure (void)\n{\n#ifdef _WIN32\n  return 0;\n#else\n  return getuid () != geteuid ()\n      || getgid () != getegid ();\n#endif\n}\n\necb_cold\nunsigned int\nev_supported_backends (void) EV_NOEXCEPT\n{\n  unsigned int flags = 0;\n\n  if (EV_USE_PORT                                      ) flags |= EVBACKEND_PORT;\n  if (EV_USE_KQUEUE                                    ) flags |= EVBACKEND_KQUEUE;\n  if (EV_USE_EPOLL                                     ) flags |= EVBACKEND_EPOLL;\n  if (EV_USE_LINUXAIO                                  ) flags |= EVBACKEND_LINUXAIO;\n  if (EV_USE_IOURING && ev_linux_version () >= 0x050601) flags |= EVBACKEND_IOURING; /* 5.6.1+ */\n  if (EV_USE_POLL                                      ) flags |= EVBACKEND_POLL;\n  if (EV_USE_SELECT                                    ) flags |= EVBACKEND_SELECT;\n\n  return flags;\n}\n\necb_cold\nunsigned int\nev_recommended_backends (void) EV_NOEXCEPT\n{\n  unsigned int flags = ev_supported_backends ();\n\n#ifndef __NetBSD__\n  /* kqueue is borked on everything but netbsd apparently */\n  /* it usually doesn't work correctly on anything but sockets and pipes */\n  flags &= ~EVBACKEND_KQUEUE;\n#endif\n#ifdef __APPLE__\n  /* only select works correctly on that \"unix-certified\" platform */\n  flags &= ~EVBACKEND_KQUEUE; /* horribly broken, even for sockets */\n  flags &= ~EVBACKEND_POLL;   /* poll is based on kqueue from 10.5 onwards */\n#endif\n#ifdef __FreeBSD__\n  flags &= ~EVBACKEND_POLL;   /* poll return value is unusable (http://forums.freebsd.org/archive/index.php/t-10270.html) */\n#endif\n\n  /* TODO: linuxaio is very experimental */\n#if !EV_RECOMMEND_LINUXAIO\n  flags &= ~EVBACKEND_LINUXAIO;\n#endif\n  /* TODO: linuxaio is super experimental */\n#if !EV_RECOMMEND_IOURING\n  flags &= ~EVBACKEND_IOURING;\n#endif\n\n  return flags;\n}\n\necb_cold\nunsigned int\nev_embeddable_backends (void) EV_NOEXCEPT\n{\n  int flags = EVBACKEND_EPOLL | EVBACKEND_KQUEUE | EVBACKEND_PORT | EVBACKEND_IOURING;\n\n  /* epoll embeddability broken on all linux versions up to at least 2.6.23 */\n  if (ev_linux_version () < 0x020620) /* disable it on linux < 2.6.32 */\n    flags &= ~EVBACKEND_EPOLL;\n\n  /* EVBACKEND_LINUXAIO is theoretically embeddable, but suffers from a performance overhead */\n\n  return flags;\n}\n\nunsigned int\nev_backend (EV_P) EV_NOEXCEPT\n{\n  return backend;\n}\n\n#if EV_FEATURE_API\nunsigned int\nev_iteration (EV_P) EV_NOEXCEPT\n{\n  return loop_count;\n}\n\nunsigned int\nev_depth (EV_P) EV_NOEXCEPT\n{\n  return loop_depth;\n}\n\nvoid\nev_set_io_collect_interval (EV_P_ ev_tstamp interval) EV_NOEXCEPT\n{\n  io_blocktime = interval;\n}\n\nvoid\nev_set_timeout_collect_interval (EV_P_ ev_tstamp interval) EV_NOEXCEPT\n{\n  timeout_blocktime = interval;\n}\n\nvoid\nev_set_userdata (EV_P_ void *data) EV_NOEXCEPT\n{\n  userdata = data;\n}\n\nvoid *\nev_userdata (EV_P) EV_NOEXCEPT\n{\n  return userdata;\n}\n\nvoid\nev_set_invoke_pending_cb (EV_P_ ev_loop_callback invoke_pending_cb) EV_NOEXCEPT\n{\n  invoke_cb = invoke_pending_cb;\n}\n\nvoid\nev_set_loop_release_cb (EV_P_ void (*release)(EV_P) EV_NOEXCEPT, void (*acquire)(EV_P) EV_NOEXCEPT) EV_NOEXCEPT\n{\n  release_cb = release;\n  acquire_cb = acquire;\n}\n#endif\n\n/* initialise a loop structure, must be zero-initialised */\necb_noinline ecb_cold\nstatic void\nloop_init (EV_P_ unsigned int flags) EV_NOEXCEPT\n{\n  if (!backend)\n    {\n      origflags = flags;\n\n#if EV_USE_REALTIME\n      if (!have_realtime)\n        {\n          struct timespec ts;\n\n          if (!clock_gettime (CLOCK_REALTIME, &ts))\n            have_realtime = 1;\n        }\n#endif\n\n#if EV_USE_MONOTONIC\n      if (!have_monotonic)\n        {\n          struct timespec ts;\n\n          if (!clock_gettime (CLOCK_MONOTONIC, &ts))\n            have_monotonic = 1;\n        }\n#endif\n\n      /* pid check not overridable via env */\n#ifndef _WIN32\n      if (flags & EVFLAG_FORKCHECK)\n        curpid = getpid ();\n#endif\n\n      if (!(flags & EVFLAG_NOENV)\n          && !enable_secure ()\n          && getenv (\"LIBEV_FLAGS\"))\n        flags = atoi (getenv (\"LIBEV_FLAGS\"));\n\n      ev_rt_now          = ev_time ();\n      mn_now             = get_clock ();\n      now_floor          = mn_now;\n      rtmn_diff          = ev_rt_now - mn_now;\n#if EV_FEATURE_API\n      invoke_cb          = ev_invoke_pending;\n#endif\n\n      io_blocktime       = 0.;\n      timeout_blocktime  = 0.;\n      backend            = 0;\n      backend_fd         = -1;\n      sig_pending        = 0;\n#if EV_ASYNC_ENABLE\n      async_pending      = 0;\n#endif\n      pipe_write_skipped = 0;\n      pipe_write_wanted  = 0;\n      evpipe [0]         = -1;\n      evpipe [1]         = -1;\n#if EV_USE_INOTIFY\n      fs_fd              = flags & EVFLAG_NOINOTIFY ? -1 : -2;\n#endif\n#if EV_USE_SIGNALFD\n      sigfd              = flags & EVFLAG_SIGNALFD  ? -2 : -1;\n#endif\n#if EV_USE_TIMERFD\n      timerfd            = flags & EVFLAG_NOTIMERFD ? -1 : -2;\n#endif\n\n      if (!(flags & EVBACKEND_MASK))\n        flags |= ev_recommended_backends ();\n\n#if EV_USE_IOCP\n      if (!backend && (flags & EVBACKEND_IOCP    )) backend = iocp_init      (EV_A_ flags);\n#endif\n#if EV_USE_PORT\n      if (!backend && (flags & EVBACKEND_PORT    )) backend = port_init      (EV_A_ flags);\n#endif\n#if EV_USE_KQUEUE\n      if (!backend && (flags & EVBACKEND_KQUEUE  )) backend = kqueue_init    (EV_A_ flags);\n#endif\n#if EV_USE_IOURING\n      if (!backend && (flags & EVBACKEND_IOURING )) backend = iouring_init   (EV_A_ flags);\n#endif\n#if EV_USE_LINUXAIO\n      if (!backend && (flags & EVBACKEND_LINUXAIO)) backend = linuxaio_init  (EV_A_ flags);\n#endif\n#if EV_USE_EPOLL\n      if (!backend && (flags & EVBACKEND_EPOLL   )) backend = epoll_init     (EV_A_ flags);\n#endif\n#if EV_USE_POLL\n      if (!backend && (flags & EVBACKEND_POLL    )) backend = poll_init      (EV_A_ flags);\n#endif\n#if EV_USE_SELECT\n      if (!backend && (flags & EVBACKEND_SELECT  )) backend = select_init    (EV_A_ flags);\n#endif\n\n      ev_prepare_init (&pending_w, pendingcb);\n\n#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE\n      ev_init (&pipe_w, pipecb);\n      ev_set_priority (&pipe_w, EV_MAXPRI);\n#endif\n    }\n}\n\n/* free up a loop structure */\necb_cold\nvoid\nev_loop_destroy (EV_P)\n{\n  int i;\n\n#if EV_MULTIPLICITY\n  /* mimic free (0) */\n  if (!EV_A)\n    return;\n#endif\n\n#if EV_CLEANUP_ENABLE\n  /* queue cleanup watchers (and execute them) */\n  if (ecb_expect_false (cleanupcnt))\n    {\n      queue_events (EV_A_ (W *)cleanups, cleanupcnt, EV_CLEANUP);\n      EV_INVOKE_PENDING;\n    }\n#endif\n\n#if EV_CHILD_ENABLE\n  if (ev_is_default_loop (EV_A) && ev_is_active (&childev))\n    {\n      ev_ref (EV_A); /* child watcher */\n      ev_signal_stop (EV_A_ &childev);\n    }\n#endif\n\n  if (ev_is_active (&pipe_w))\n    {\n      /*ev_ref (EV_A);*/\n      /*ev_io_stop (EV_A_ &pipe_w);*/\n\n      if (evpipe [0] >= 0) EV_WIN32_CLOSE_FD (evpipe [0]);\n      if (evpipe [1] >= 0) EV_WIN32_CLOSE_FD (evpipe [1]);\n    }\n\n#if EV_USE_SIGNALFD\n  if (ev_is_active (&sigfd_w))\n    close (sigfd);\n#endif\n\n#if EV_USE_TIMERFD\n  if (ev_is_active (&timerfd_w))\n    close (timerfd);\n#endif\n\n#if EV_USE_INOTIFY\n  if (fs_fd >= 0)\n    close (fs_fd);\n#endif\n\n  if (backend_fd >= 0)\n    close (backend_fd);\n\n#if EV_USE_IOCP\n  if (backend == EVBACKEND_IOCP    ) iocp_destroy     (EV_A);\n#endif\n#if EV_USE_PORT\n  if (backend == EVBACKEND_PORT    ) port_destroy     (EV_A);\n#endif\n#if EV_USE_KQUEUE\n  if (backend == EVBACKEND_KQUEUE  ) kqueue_destroy   (EV_A);\n#endif\n#if EV_USE_IOURING\n  if (backend == EVBACKEND_IOURING ) iouring_destroy  (EV_A);\n#endif\n#if EV_USE_LINUXAIO\n  if (backend == EVBACKEND_LINUXAIO) linuxaio_destroy (EV_A);\n#endif\n#if EV_USE_EPOLL\n  if (backend == EVBACKEND_EPOLL   ) epoll_destroy    (EV_A);\n#endif\n#if EV_USE_POLL\n  if (backend == EVBACKEND_POLL    ) poll_destroy     (EV_A);\n#endif\n#if EV_USE_SELECT\n  if (backend == EVBACKEND_SELECT  ) select_destroy   (EV_A);\n#endif\n\n  for (i = NUMPRI; i--; )\n    {\n      array_free (pending, [i]);\n#if EV_IDLE_ENABLE\n      array_free (idle, [i]);\n#endif\n    }\n\n  ev_free (anfds); anfds = 0; anfdmax = 0;\n\n  /* have to use the microsoft-never-gets-it-right macro */\n  array_free (rfeed, EMPTY);\n  array_free (fdchange, EMPTY);\n  array_free (timer, EMPTY);\n#if EV_PERIODIC_ENABLE\n  array_free (periodic, EMPTY);\n#endif\n#if EV_FORK_ENABLE\n  array_free (fork, EMPTY);\n#endif\n#if EV_CLEANUP_ENABLE\n  array_free (cleanup, EMPTY);\n#endif\n  array_free (prepare, EMPTY);\n  array_free (check, EMPTY);\n#if EV_ASYNC_ENABLE\n  array_free (async, EMPTY);\n#endif\n\n  backend = 0;\n\n#if EV_MULTIPLICITY\n  if (ev_is_default_loop (EV_A))\n#endif\n    ev_default_loop_ptr = 0;\n#if EV_MULTIPLICITY\n  else\n    ev_free (EV_A);\n#endif\n}\n\n#if EV_USE_INOTIFY\ninline_size void infy_fork (EV_P);\n#endif\n\ninline_size void\nloop_fork (EV_P)\n{\n#if EV_USE_PORT\n  if (backend == EVBACKEND_PORT    ) port_fork     (EV_A);\n#endif\n#if EV_USE_KQUEUE\n  if (backend == EVBACKEND_KQUEUE  ) kqueue_fork   (EV_A);\n#endif\n#if EV_USE_IOURING\n  if (backend == EVBACKEND_IOURING ) iouring_fork  (EV_A);\n#endif\n#if EV_USE_LINUXAIO\n  if (backend == EVBACKEND_LINUXAIO) linuxaio_fork (EV_A);\n#endif\n#if EV_USE_EPOLL\n  if (backend == EVBACKEND_EPOLL   ) epoll_fork    (EV_A);\n#endif\n#if EV_USE_INOTIFY\n  infy_fork (EV_A);\n#endif\n\n  if (postfork != 2)\n    {\n      #if EV_USE_SIGNALFD\n        /* surprisingly, nothing needs to be done for signalfd, accoridng to docs, it does the right thing on fork */\n      #endif\n      \n      #if EV_USE_TIMERFD\n        if (ev_is_active (&timerfd_w))\n          {\n            ev_ref (EV_A);\n            ev_io_stop (EV_A_ &timerfd_w);\n\n            close (timerfd);\n            timerfd = -2;\n      \n            evtimerfd_init (EV_A);\n            /* reschedule periodics, in case we missed something */\n            ev_feed_event (EV_A_ &timerfd_w, EV_CUSTOM);\n          }\n      #endif\n      \n      #if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE\n        if (ev_is_active (&pipe_w))\n          {\n            /* pipe_write_wanted must be false now, so modifying fd vars should be safe */\n      \n            ev_ref (EV_A);\n            ev_io_stop (EV_A_ &pipe_w);\n      \n            if (evpipe [0] >= 0)\n              EV_WIN32_CLOSE_FD (evpipe [0]);\n      \n            evpipe_init (EV_A);\n            /* iterate over everything, in case we missed something before */\n            ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM);\n          }\n      #endif\n    }\n\n  postfork = 0;\n}\n\n#if EV_MULTIPLICITY\n\necb_cold\nstruct ev_loop *\nev_loop_new (unsigned int flags) EV_NOEXCEPT\n{\n  EV_P = (struct ev_loop *)ev_malloc (sizeof (struct ev_loop));\n\n  memset (EV_A, 0, sizeof (struct ev_loop));\n  loop_init (EV_A_ flags);\n\n  if (ev_backend (EV_A))\n    return EV_A;\n\n  ev_free (EV_A);\n  return 0;\n}\n\n#endif /* multiplicity */\n\n#if EV_VERIFY\necb_noinline ecb_cold\nstatic void\nverify_watcher (EV_P_ W w)\n{\n  assert ((\"libev: watcher has invalid priority\", ABSPRI (w) >= 0 && ABSPRI (w) < NUMPRI));\n\n  if (w->pending)\n    assert ((\"libev: pending watcher not on pending queue\", pendings [ABSPRI (w)][w->pending - 1].w == w));\n}\n\necb_noinline ecb_cold\nstatic void\nverify_heap (EV_P_ ANHE *heap, int N)\n{\n  int i;\n\n  for (i = HEAP0; i < N + HEAP0; ++i)\n    {\n      assert ((\"libev: active index mismatch in heap\", ev_active (ANHE_w (heap [i])) == i));\n      assert ((\"libev: heap condition violated\", i == HEAP0 || ANHE_at (heap [HPARENT (i)]) <= ANHE_at (heap [i])));\n      assert ((\"libev: heap at cache mismatch\", ANHE_at (heap [i]) == ev_at (ANHE_w (heap [i]))));\n\n      verify_watcher (EV_A_ (W)ANHE_w (heap [i]));\n    }\n}\n\necb_noinline ecb_cold\nstatic void\narray_verify (EV_P_ W *ws, int cnt)\n{\n  while (cnt--)\n    {\n      assert ((\"libev: active index mismatch\", ev_active (ws [cnt]) == cnt + 1));\n      verify_watcher (EV_A_ ws [cnt]);\n    }\n}\n#endif\n\n#if EV_FEATURE_API\nvoid ecb_cold\nev_verify (EV_P) EV_NOEXCEPT\n{\n#if EV_VERIFY\n  int i;\n  WL w, w2;\n\n  assert (activecnt >= -1);\n\n  assert (fdchangemax >= fdchangecnt);\n  for (i = 0; i < fdchangecnt; ++i)\n    assert ((\"libev: negative fd in fdchanges\", fdchanges [i] >= 0));\n\n  assert (anfdmax >= 0);\n  for (i = 0; i < anfdmax; ++i)\n    {\n      int j = 0;\n\n      for (w = w2 = anfds [i].head; w; w = w->next)\n        {\n          verify_watcher (EV_A_ (W)w);\n\n          if (j++ & 1)\n            {\n              assert ((\"libev: io watcher list contains a loop\", w != w2));\n              w2 = w2->next;\n            }\n\n          assert ((\"libev: inactive fd watcher on anfd list\", ev_active (w) == 1));\n          assert ((\"libev: fd mismatch between watcher and anfd\", ((ev_io *)w)->fd == i));\n        }\n    }\n\n  assert (timermax >= timercnt);\n  verify_heap (EV_A_ timers, timercnt);\n\n#if EV_PERIODIC_ENABLE\n  assert (periodicmax >= periodiccnt);\n  verify_heap (EV_A_ periodics, periodiccnt);\n#endif\n\n  for (i = NUMPRI; i--; )\n    {\n      assert (pendingmax [i] >= pendingcnt [i]);\n#if EV_IDLE_ENABLE\n      assert (idleall >= 0);\n      assert (idlemax [i] >= idlecnt [i]);\n      array_verify (EV_A_ (W *)idles [i], idlecnt [i]);\n#endif\n    }\n\n#if EV_FORK_ENABLE\n  assert (forkmax >= forkcnt);\n  array_verify (EV_A_ (W *)forks, forkcnt);\n#endif\n\n#if EV_CLEANUP_ENABLE\n  assert (cleanupmax >= cleanupcnt);\n  array_verify (EV_A_ (W *)cleanups, cleanupcnt);\n#endif\n\n#if EV_ASYNC_ENABLE\n  assert (asyncmax >= asynccnt);\n  array_verify (EV_A_ (W *)asyncs, asynccnt);\n#endif\n\n#if EV_PREPARE_ENABLE\n  assert (preparemax >= preparecnt);\n  array_verify (EV_A_ (W *)prepares, preparecnt);\n#endif\n\n#if EV_CHECK_ENABLE\n  assert (checkmax >= checkcnt);\n  array_verify (EV_A_ (W *)checks, checkcnt);\n#endif\n\n# if 0\n#if EV_CHILD_ENABLE\n  for (w = (ev_child *)childs [chain & ((EV_PID_HASHSIZE) - 1)]; w; w = (ev_child *)((WL)w)->next)\n  for (signum = EV_NSIG; signum--; ) if (signals [signum].pending)\n#endif\n# endif\n#endif\n}\n#endif\n\n#if EV_MULTIPLICITY\necb_cold\nstruct ev_loop *\n#else\nint\n#endif\nev_default_loop (unsigned int flags) EV_NOEXCEPT\n{\n  if (!ev_default_loop_ptr)\n    {\n#if EV_MULTIPLICITY\n      EV_P = ev_default_loop_ptr = &default_loop_struct;\n#else\n      ev_default_loop_ptr = 1;\n#endif\n\n      loop_init (EV_A_ flags);\n\n      if (ev_backend (EV_A))\n        {\n#if EV_CHILD_ENABLE\n          ev_signal_init (&childev, childcb, SIGCHLD);\n          ev_set_priority (&childev, EV_MAXPRI);\n          ev_signal_start (EV_A_ &childev);\n          ev_unref (EV_A); /* child watcher should not keep loop alive */\n#endif\n        }\n      else\n        ev_default_loop_ptr = 0;\n    }\n\n  return ev_default_loop_ptr;\n}\n\nvoid\nev_loop_fork (EV_P) EV_NOEXCEPT\n{\n  postfork = 1;\n}\n\n/*****************************************************************************/\n\nvoid\nev_invoke (EV_P_ void *w, int revents)\n{\n  EV_CB_INVOKE ((W)w, revents);\n}\n\nunsigned int\nev_pending_count (EV_P) EV_NOEXCEPT\n{\n  int pri;\n  unsigned int count = 0;\n\n  for (pri = NUMPRI; pri--; )\n    count += pendingcnt [pri];\n\n  return count;\n}\n\necb_noinline\nvoid\nev_invoke_pending (EV_P)\n{\n  pendingpri = NUMPRI;\n\n  do\n    {\n      --pendingpri;\n\n      /* pendingpri possibly gets modified in the inner loop */\n      while (pendingcnt [pendingpri])\n        {\n          ANPENDING *p = pendings [pendingpri] + --pendingcnt [pendingpri];\n\n          p->w->pending = 0;\n          EV_CB_INVOKE (p->w, p->events);\n          EV_FREQUENT_CHECK;\n        }\n    }\n  while (pendingpri);\n}\n\n#if EV_IDLE_ENABLE\n/* make idle watchers pending. this handles the \"call-idle */\n/* only when higher priorities are idle\" logic */\ninline_size void\nidle_reify (EV_P)\n{\n  if (ecb_expect_false (idleall))\n    {\n      int pri;\n\n      for (pri = NUMPRI; pri--; )\n        {\n          if (pendingcnt [pri])\n            break;\n\n          if (idlecnt [pri])\n            {\n              queue_events (EV_A_ (W *)idles [pri], idlecnt [pri], EV_IDLE);\n              break;\n            }\n        }\n    }\n}\n#endif\n\n/* make timers pending */\ninline_size void\ntimers_reify (EV_P)\n{\n  EV_FREQUENT_CHECK;\n\n  if (timercnt && ANHE_at (timers [HEAP0]) < mn_now)\n    {\n      do\n        {\n          ev_timer *w = (ev_timer *)ANHE_w (timers [HEAP0]);\n\n          /*assert ((\"libev: inactive timer on timer heap detected\", ev_is_active (w)));*/\n\n          /* first reschedule or stop timer */\n          if (w->repeat)\n            {\n              ev_at (w) += w->repeat;\n              if (ev_at (w) < mn_now)\n                ev_at (w) = mn_now;\n\n              assert ((\"libev: negative ev_timer repeat value found while processing timers\", w->repeat > EV_TS_CONST (0.)));\n\n              ANHE_at_cache (timers [HEAP0]);\n              downheap (timers, timercnt, HEAP0);\n            }\n          else\n            ev_timer_stop (EV_A_ w); /* nonrepeating: stop timer */\n\n          EV_FREQUENT_CHECK;\n          feed_reverse (EV_A_ (W)w);\n        }\n      while (timercnt && ANHE_at (timers [HEAP0]) < mn_now);\n\n      feed_reverse_done (EV_A_ EV_TIMER);\n    }\n}\n\n#if EV_PERIODIC_ENABLE\n\necb_noinline\nstatic void\nperiodic_recalc (EV_P_ ev_periodic *w)\n{\n  ev_tstamp interval = w->interval > MIN_INTERVAL ? w->interval : MIN_INTERVAL;\n  ev_tstamp at = w->offset + interval * ev_floor ((ev_rt_now - w->offset) / interval);\n\n  /* the above almost always errs on the low side */\n  while (at <= ev_rt_now)\n    {\n      ev_tstamp nat = at + w->interval;\n\n      /* when resolution fails us, we use ev_rt_now */\n      if (ecb_expect_false (nat == at))\n        {\n          at = ev_rt_now;\n          break;\n        }\n\n      at = nat;\n    }\n\n  ev_at (w) = at;\n}\n\n/* make periodics pending */\ninline_size void\nperiodics_reify (EV_P)\n{\n  EV_FREQUENT_CHECK;\n\n  while (periodiccnt && ANHE_at (periodics [HEAP0]) < ev_rt_now)\n    {\n      do\n        {\n          ev_periodic *w = (ev_periodic *)ANHE_w (periodics [HEAP0]);\n\n          /*assert ((\"libev: inactive timer on periodic heap detected\", ev_is_active (w)));*/\n\n          /* first reschedule or stop timer */\n          if (w->reschedule_cb)\n            {\n              ev_at (w) = w->reschedule_cb (w, ev_rt_now);\n\n              assert ((\"libev: ev_periodic reschedule callback returned time in the past\", ev_at (w) >= ev_rt_now));\n\n              ANHE_at_cache (periodics [HEAP0]);\n              downheap (periodics, periodiccnt, HEAP0);\n            }\n          else if (w->interval)\n            {\n              periodic_recalc (EV_A_ w);\n              ANHE_at_cache (periodics [HEAP0]);\n              downheap (periodics, periodiccnt, HEAP0);\n            }\n          else\n            ev_periodic_stop (EV_A_ w); /* nonrepeating: stop timer */\n\n          EV_FREQUENT_CHECK;\n          feed_reverse (EV_A_ (W)w);\n        }\n      while (periodiccnt && ANHE_at (periodics [HEAP0]) < ev_rt_now);\n\n      feed_reverse_done (EV_A_ EV_PERIODIC);\n    }\n}\n\n/* simply recalculate all periodics */\n/* TODO: maybe ensure that at least one event happens when jumping forward? */\necb_noinline ecb_cold\nstatic void\nperiodics_reschedule (EV_P)\n{\n  int i;\n\n  /* adjust periodics after time jump */\n  for (i = HEAP0; i < periodiccnt + HEAP0; ++i)\n    {\n      ev_periodic *w = (ev_periodic *)ANHE_w (periodics [i]);\n\n      if (w->reschedule_cb)\n        ev_at (w) = w->reschedule_cb (w, ev_rt_now);\n      else if (w->interval)\n        periodic_recalc (EV_A_ w);\n\n      ANHE_at_cache (periodics [i]);\n    }\n\n  reheap (periodics, periodiccnt);\n}\n#endif\n\n/* adjust all timers by a given offset */\necb_noinline ecb_cold\nstatic void\ntimers_reschedule (EV_P_ ev_tstamp adjust)\n{\n  int i;\n\n  for (i = 0; i < timercnt; ++i)\n    {\n      ANHE *he = timers + i + HEAP0;\n      ANHE_w (*he)->at += adjust;\n      ANHE_at_cache (*he);\n    }\n}\n\n/* fetch new monotonic and realtime times from the kernel */\n/* also detect if there was a timejump, and act accordingly */\ninline_speed void\ntime_update (EV_P_ ev_tstamp max_block)\n{\n#if EV_USE_MONOTONIC\n  if (ecb_expect_true (have_monotonic))\n    {\n      int i;\n      ev_tstamp odiff = rtmn_diff;\n\n      mn_now = get_clock ();\n\n      /* only fetch the realtime clock every 0.5*MIN_TIMEJUMP seconds */\n      /* interpolate in the meantime */\n      if (ecb_expect_true (mn_now - now_floor < EV_TS_CONST (MIN_TIMEJUMP * .5)))\n        {\n          ev_rt_now = rtmn_diff + mn_now;\n          return;\n        }\n\n      now_floor = mn_now;\n      ev_rt_now = ev_time ();\n\n      /* loop a few times, before making important decisions.\n       * on the choice of \"4\": one iteration isn't enough,\n       * in case we get preempted during the calls to\n       * ev_time and get_clock. a second call is almost guaranteed\n       * to succeed in that case, though. and looping a few more times\n       * doesn't hurt either as we only do this on time-jumps or\n       * in the unlikely event of having been preempted here.\n       */\n      for (i = 4; --i; )\n        {\n          ev_tstamp diff;\n          rtmn_diff = ev_rt_now - mn_now;\n\n          diff = odiff - rtmn_diff;\n\n          if (ecb_expect_true ((diff < EV_TS_CONST (0.) ? -diff : diff) < EV_TS_CONST (MIN_TIMEJUMP)))\n            return; /* all is well */\n\n          ev_rt_now = ev_time ();\n          mn_now    = get_clock ();\n          now_floor = mn_now;\n        }\n\n      /* no timer adjustment, as the monotonic clock doesn't jump */\n      /* timers_reschedule (EV_A_ rtmn_diff - odiff) */\n# if EV_PERIODIC_ENABLE\n      periodics_reschedule (EV_A);\n# endif\n    }\n  else\n#endif\n    {\n      ev_rt_now = ev_time ();\n\n      if (ecb_expect_false (mn_now > ev_rt_now || ev_rt_now > mn_now + max_block + EV_TS_CONST (MIN_TIMEJUMP)))\n        {\n          /* adjust timers. this is easy, as the offset is the same for all of them */\n          timers_reschedule (EV_A_ ev_rt_now - mn_now);\n#if EV_PERIODIC_ENABLE\n          periodics_reschedule (EV_A);\n#endif\n        }\n\n      mn_now = ev_rt_now;\n    }\n}\n\nint\nev_run (EV_P_ int flags)\n{\n#if EV_FEATURE_API\n  ++loop_depth;\n#endif\n\n  assert ((\"libev: ev_loop recursion during release detected\", loop_done != EVBREAK_RECURSE));\n\n  loop_done = EVBREAK_CANCEL;\n\n  EV_INVOKE_PENDING; /* in case we recurse, ensure ordering stays nice and clean */\n\n  do\n    {\n#if EV_VERIFY >= 2\n      ev_verify (EV_A);\n#endif\n\n#ifndef _WIN32\n      if (ecb_expect_false (curpid)) /* penalise the forking check even more */\n        if (ecb_expect_false (getpid () != curpid))\n          {\n            curpid = getpid ();\n            postfork = 1;\n          }\n#endif\n\n#if EV_FORK_ENABLE\n      /* we might have forked, so queue fork handlers */\n      if (ecb_expect_false (postfork))\n        if (forkcnt)\n          {\n            queue_events (EV_A_ (W *)forks, forkcnt, EV_FORK);\n            EV_INVOKE_PENDING;\n          }\n#endif\n\n#if EV_PREPARE_ENABLE\n      /* queue prepare watchers (and execute them) */\n      if (ecb_expect_false (preparecnt))\n        {\n          queue_events (EV_A_ (W *)prepares, preparecnt, EV_PREPARE);\n          EV_INVOKE_PENDING;\n        }\n#endif\n\n      if (ecb_expect_false (loop_done))\n        break;\n\n      /* we might have forked, so reify kernel state if necessary */\n      if (ecb_expect_false (postfork))\n        loop_fork (EV_A);\n\n      /* update fd-related kernel structures */\n      fd_reify (EV_A);\n\n      /* calculate blocking time */\n      {\n        ev_tstamp waittime  = 0.;\n        ev_tstamp sleeptime = 0.;\n\n        /* remember old timestamp for io_blocktime calculation */\n        ev_tstamp prev_mn_now = mn_now;\n\n        /* update time to cancel out callback processing overhead */\n        time_update (EV_A_ EV_TS_CONST (EV_TSTAMP_HUGE));\n\n        /* from now on, we want a pipe-wake-up */\n        pipe_write_wanted = 1;\n\n        ECB_MEMORY_FENCE; /* make sure pipe_write_wanted is visible before we check for potential skips */\n\n        if (ecb_expect_true (!(flags & EVRUN_NOWAIT || idleall || !activecnt || pipe_write_skipped)))\n          {\n            waittime = EV_TS_CONST (MAX_BLOCKTIME);\n\n#if EV_USE_TIMERFD\n            /* sleep a lot longer when we can reliably detect timejumps */\n            if (ecb_expect_true (timerfd >= 0))\n              waittime = EV_TS_CONST (MAX_BLOCKTIME2);\n#endif\n#if !EV_PERIODIC_ENABLE && EV_USE_MONOTONIC\n            /* without periodics but with monotonic clock there is no need */\n            /* for any time jump detection, so sleep longer */\n            if (ecb_expect_true (have_monotonic))\n              waittime = EV_TS_CONST (MAX_BLOCKTIME2);\n#endif\n\n            if (timercnt)\n              {\n                ev_tstamp to = ANHE_at (timers [HEAP0]) - mn_now;\n                if (waittime > to) waittime = to;\n              }\n\n#if EV_PERIODIC_ENABLE\n            if (periodiccnt)\n              {\n                ev_tstamp to = ANHE_at (periodics [HEAP0]) - ev_rt_now;\n                if (waittime > to) waittime = to;\n              }\n#endif\n\n            /* don't let timeouts decrease the waittime below timeout_blocktime */\n            if (ecb_expect_false (waittime < timeout_blocktime))\n              waittime = timeout_blocktime;\n\n            /* now there are two more special cases left, either we have\n             * already-expired timers, so we should not sleep, or we have timers\n             * that expire very soon, in which case we need to wait for a minimum\n             * amount of time for some event loop backends.\n             */\n            if (ecb_expect_false (waittime < backend_mintime))\n              waittime = waittime <= EV_TS_CONST (0.)\n                 ? EV_TS_CONST (0.)\n                 : backend_mintime;\n\n            /* extra check because io_blocktime is commonly 0 */\n            if (ecb_expect_false (io_blocktime))\n              {\n                sleeptime = io_blocktime - (mn_now - prev_mn_now);\n\n                if (sleeptime > waittime - backend_mintime)\n                  sleeptime = waittime - backend_mintime;\n\n                if (ecb_expect_true (sleeptime > EV_TS_CONST (0.)))\n                  {\n                    ev_sleep (sleeptime);\n                    waittime -= sleeptime;\n                  }\n              }\n          }\n\n#if EV_FEATURE_API\n        ++loop_count;\n#endif\n        assert ((loop_done = EVBREAK_RECURSE, 1)); /* assert for side effect */\n        backend_poll (EV_A_ waittime);\n        assert ((loop_done = EVBREAK_CANCEL, 1)); /* assert for side effect */\n\n        pipe_write_wanted = 0; /* just an optimisation, no fence needed */\n\n        ECB_MEMORY_FENCE_ACQUIRE;\n        if (pipe_write_skipped)\n          {\n            assert ((\"libev: pipe_w not active, but pipe not written\", ev_is_active (&pipe_w)));\n            ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM);\n          }\n\n        /* update ev_rt_now, do magic */\n        time_update (EV_A_ waittime + sleeptime);\n      }\n\n      /* queue pending timers and reschedule them */\n      timers_reify (EV_A); /* relative timers called last */\n#if EV_PERIODIC_ENABLE\n      periodics_reify (EV_A); /* absolute timers called first */\n#endif\n\n#if EV_IDLE_ENABLE\n      /* queue idle watchers unless other events are pending */\n      idle_reify (EV_A);\n#endif\n\n#if EV_CHECK_ENABLE\n      /* queue check watchers, to be executed first */\n      if (ecb_expect_false (checkcnt))\n        queue_events (EV_A_ (W *)checks, checkcnt, EV_CHECK);\n#endif\n\n      EV_INVOKE_PENDING;\n    }\n  while (ecb_expect_true (\n    activecnt\n    && !loop_done\n    && !(flags & (EVRUN_ONCE | EVRUN_NOWAIT))\n  ));\n\n  if (loop_done == EVBREAK_ONE)\n    loop_done = EVBREAK_CANCEL;\n\n#if EV_FEATURE_API\n  --loop_depth;\n#endif\n\n  return activecnt;\n}\n\nvoid\nev_break (EV_P_ int how) EV_NOEXCEPT\n{\n  loop_done = how;\n}\n\nvoid\nev_ref (EV_P) EV_NOEXCEPT\n{\n  ++activecnt;\n}\n\nvoid\nev_unref (EV_P) EV_NOEXCEPT\n{\n  --activecnt;\n}\n\nvoid\nev_now_update (EV_P) EV_NOEXCEPT\n{\n  time_update (EV_A_ EV_TSTAMP_HUGE);\n}\n\nvoid\nev_suspend (EV_P) EV_NOEXCEPT\n{\n  ev_now_update (EV_A);\n}\n\nvoid\nev_resume (EV_P) EV_NOEXCEPT\n{\n  ev_tstamp mn_prev = mn_now;\n\n  ev_now_update (EV_A);\n  timers_reschedule (EV_A_ mn_now - mn_prev);\n#if EV_PERIODIC_ENABLE\n  /* TODO: really do this? */\n  periodics_reschedule (EV_A);\n#endif\n}\n\n/*****************************************************************************/\n/* singly-linked list management, used when the expected list length is short */\n\ninline_size void\nwlist_add (WL *head, WL elem)\n{\n  elem->next = *head;\n  *head = elem;\n}\n\ninline_size void\nwlist_del (WL *head, WL elem)\n{\n  while (*head)\n    {\n      if (ecb_expect_true (*head == elem))\n        {\n          *head = elem->next;\n          break;\n        }\n\n      head = &(*head)->next;\n    }\n}\n\n/* internal, faster, version of ev_clear_pending */\ninline_speed void\nclear_pending (EV_P_ W w)\n{\n  if (w->pending)\n    {\n      pendings [ABSPRI (w)][w->pending - 1].w = (W)&pending_w;\n      w->pending = 0;\n    }\n}\n\nint\nev_clear_pending (EV_P_ void *w) EV_NOEXCEPT\n{\n  W w_ = (W)w;\n  int pending = w_->pending;\n\n  if (ecb_expect_true (pending))\n    {\n      ANPENDING *p = pendings [ABSPRI (w_)] + pending - 1;\n      p->w = (W)&pending_w;\n      w_->pending = 0;\n      return p->events;\n    }\n  else\n    return 0;\n}\n\ninline_size void\npri_adjust (EV_P_ W w)\n{\n  int pri = ev_priority (w);\n  pri = pri < EV_MINPRI ? EV_MINPRI : pri;\n  pri = pri > EV_MAXPRI ? EV_MAXPRI : pri;\n  ev_set_priority (w, pri);\n}\n\ninline_speed void\nev_start (EV_P_ W w, int active)\n{\n  pri_adjust (EV_A_ w);\n  w->active = active;\n  ev_ref (EV_A);\n}\n\ninline_size void\nev_stop (EV_P_ W w)\n{\n  ev_unref (EV_A);\n  w->active = 0;\n}\n\n/*****************************************************************************/\n\necb_noinline\nvoid\nev_io_start (EV_P_ ev_io *w) EV_NOEXCEPT\n{\n  int fd = w->fd;\n\n  if (ecb_expect_false (ev_is_active (w)))\n    return;\n\n  assert ((\"libev: ev_io_start called with negative fd\", fd >= 0));\n  assert ((\"libev: ev_io_start called with illegal event mask\", !(w->events & ~(EV__IOFDSET | EV_READ | EV_WRITE | EV_CUSTOM))));\n\n#if EV_VERIFY >= 2\n  assert ((\"libev: ev_io_start called on watcher with invalid fd\", fd_valid (fd)));\n#endif\n  EV_FREQUENT_CHECK;\n\n  ev_start (EV_A_ (W)w, 1);\n  array_needsize (ANFD, anfds, anfdmax, fd + 1, array_needsize_zerofill);\n  wlist_add (&anfds[fd].head, (WL)w);\n\n  /* common bug, apparently */\n  assert ((\"libev: ev_io_start called with corrupted watcher\", ((WL)w)->next != (WL)w));\n\n  fd_change (EV_A_ fd, (w->events & EV__IOFDSET) | EV_ANFD_REIFY);\n  w->events &= ~EV__IOFDSET;\n\n  EV_FREQUENT_CHECK;\n}\n\necb_noinline\nvoid\nev_io_stop (EV_P_ ev_io *w) EV_NOEXCEPT\n{\n  clear_pending (EV_A_ (W)w);\n  if (ecb_expect_false (!ev_is_active (w)))\n    return;\n\n  assert ((\"libev: ev_io_stop called with illegal fd (must stay constant after start!)\", w->fd >= 0 && w->fd < anfdmax));\n\n#if EV_VERIFY >= 2\n  assert ((\"libev: ev_io_stop called on watcher with invalid fd\", fd_valid (w->fd)));\n#endif\n  EV_FREQUENT_CHECK;\n\n  wlist_del (&anfds[w->fd].head, (WL)w);\n  ev_stop (EV_A_ (W)w);\n\n  fd_change (EV_A_ w->fd, EV_ANFD_REIFY);\n\n  EV_FREQUENT_CHECK;\n}\n\necb_noinline\nvoid\nev_timer_start (EV_P_ ev_timer *w) EV_NOEXCEPT\n{\n  if (ecb_expect_false (ev_is_active (w)))\n    return;\n\n  ev_at (w) += mn_now;\n\n  assert ((\"libev: ev_timer_start called with negative timer repeat value\", w->repeat >= 0.));\n\n  EV_FREQUENT_CHECK;\n\n  ++timercnt;\n  ev_start (EV_A_ (W)w, timercnt + HEAP0 - 1);\n  array_needsize (ANHE, timers, timermax, ev_active (w) + 1, array_needsize_noinit);\n  ANHE_w (timers [ev_active (w)]) = (WT)w;\n  ANHE_at_cache (timers [ev_active (w)]);\n  upheap (timers, ev_active (w));\n\n  EV_FREQUENT_CHECK;\n\n  /*assert ((\"libev: internal timer heap corruption\", timers [ev_active (w)] == (WT)w));*/\n}\n\necb_noinline\nvoid\nev_timer_stop (EV_P_ ev_timer *w) EV_NOEXCEPT\n{\n  clear_pending (EV_A_ (W)w);\n  if (ecb_expect_false (!ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  {\n    int active = ev_active (w);\n\n    assert ((\"libev: internal timer heap corruption\", ANHE_w (timers [active]) == (WT)w));\n\n    --timercnt;\n\n    if (ecb_expect_true (active < timercnt + HEAP0))\n      {\n        timers [active] = timers [timercnt + HEAP0];\n        adjustheap (timers, timercnt, active);\n      }\n  }\n\n  ev_at (w) -= mn_now;\n\n  ev_stop (EV_A_ (W)w);\n\n  EV_FREQUENT_CHECK;\n}\n\necb_noinline\nvoid\nev_timer_again (EV_P_ ev_timer *w) EV_NOEXCEPT\n{\n  EV_FREQUENT_CHECK;\n\n  clear_pending (EV_A_ (W)w);\n\n  if (ev_is_active (w))\n    {\n      if (w->repeat)\n        {\n          ev_at (w) = mn_now + w->repeat;\n          ANHE_at_cache (timers [ev_active (w)]);\n          adjustheap (timers, timercnt, ev_active (w));\n        }\n      else\n        ev_timer_stop (EV_A_ w);\n    }\n  else if (w->repeat)\n    {\n      ev_at (w) = w->repeat;\n      ev_timer_start (EV_A_ w);\n    }\n\n  EV_FREQUENT_CHECK;\n}\n\nev_tstamp\nev_timer_remaining (EV_P_ ev_timer *w) EV_NOEXCEPT\n{\n  return ev_at (w) - (ev_is_active (w) ? mn_now : EV_TS_CONST (0.));\n}\n\n#if EV_PERIODIC_ENABLE\necb_noinline\nvoid\nev_periodic_start (EV_P_ ev_periodic *w) EV_NOEXCEPT\n{\n  if (ecb_expect_false (ev_is_active (w)))\n    return;\n\n#if EV_USE_TIMERFD\n  if (timerfd == -2)\n    evtimerfd_init (EV_A);\n#endif\n\n  if (w->reschedule_cb)\n    ev_at (w) = w->reschedule_cb (w, ev_rt_now);\n  else if (w->interval)\n    {\n      assert ((\"libev: ev_periodic_start called with negative interval value\", w->interval >= 0.));\n      periodic_recalc (EV_A_ w);\n    }\n  else\n    ev_at (w) = w->offset;\n\n  EV_FREQUENT_CHECK;\n\n  ++periodiccnt;\n  ev_start (EV_A_ (W)w, periodiccnt + HEAP0 - 1);\n  array_needsize (ANHE, periodics, periodicmax, ev_active (w) + 1, array_needsize_noinit);\n  ANHE_w (periodics [ev_active (w)]) = (WT)w;\n  ANHE_at_cache (periodics [ev_active (w)]);\n  upheap (periodics, ev_active (w));\n\n  EV_FREQUENT_CHECK;\n\n  /*assert ((\"libev: internal periodic heap corruption\", ANHE_w (periodics [ev_active (w)]) == (WT)w));*/\n}\n\necb_noinline\nvoid\nev_periodic_stop (EV_P_ ev_periodic *w) EV_NOEXCEPT\n{\n  clear_pending (EV_A_ (W)w);\n  if (ecb_expect_false (!ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  {\n    int active = ev_active (w);\n\n    assert ((\"libev: internal periodic heap corruption\", ANHE_w (periodics [active]) == (WT)w));\n\n    --periodiccnt;\n\n    if (ecb_expect_true (active < periodiccnt + HEAP0))\n      {\n        periodics [active] = periodics [periodiccnt + HEAP0];\n        adjustheap (periodics, periodiccnt, active);\n      }\n  }\n\n  ev_stop (EV_A_ (W)w);\n\n  EV_FREQUENT_CHECK;\n}\n\necb_noinline\nvoid\nev_periodic_again (EV_P_ ev_periodic *w) EV_NOEXCEPT\n{\n  /* TODO: use adjustheap and recalculation */\n  ev_periodic_stop (EV_A_ w);\n  ev_periodic_start (EV_A_ w);\n}\n#endif\n\n#ifndef SA_RESTART\n# define SA_RESTART 0\n#endif\n\n#if EV_SIGNAL_ENABLE\n\necb_noinline\nvoid\nev_signal_start (EV_P_ ev_signal *w) EV_NOEXCEPT\n{\n  if (ecb_expect_false (ev_is_active (w)))\n    return;\n\n  assert ((\"libev: ev_signal_start called with illegal signal number\", w->signum > 0 && w->signum < EV_NSIG));\n\n#if EV_MULTIPLICITY\n  assert ((\"libev: a signal must not be attached to two different loops\",\n           !signals [w->signum - 1].loop || signals [w->signum - 1].loop == loop));\n\n  signals [w->signum - 1].loop = EV_A;\n  ECB_MEMORY_FENCE_RELEASE;\n#endif\n\n  EV_FREQUENT_CHECK;\n\n#if EV_USE_SIGNALFD\n  if (sigfd == -2)\n    {\n      sigfd = signalfd (-1, &sigfd_set, SFD_NONBLOCK | SFD_CLOEXEC);\n      if (sigfd < 0 && errno == EINVAL)\n        sigfd = signalfd (-1, &sigfd_set, 0); /* retry without flags */\n\n      if (sigfd >= 0)\n        {\n          fd_intern (sigfd); /* doing it twice will not hurt */\n\n          sigemptyset (&sigfd_set);\n\n          ev_io_init (&sigfd_w, sigfdcb, sigfd, EV_READ);\n          ev_set_priority (&sigfd_w, EV_MAXPRI);\n          ev_io_start (EV_A_ &sigfd_w);\n          ev_unref (EV_A); /* signalfd watcher should not keep loop alive */\n        }\n    }\n\n  if (sigfd >= 0)\n    {\n      /* TODO: check .head */\n      sigaddset (&sigfd_set, w->signum);\n      sigprocmask (SIG_BLOCK, &sigfd_set, 0);\n\n      signalfd (sigfd, &sigfd_set, 0);\n    }\n#endif\n\n  ev_start (EV_A_ (W)w, 1);\n  wlist_add (&signals [w->signum - 1].head, (WL)w);\n\n  if (!((WL)w)->next)\n# if EV_USE_SIGNALFD\n    if (sigfd < 0) /*TODO*/\n# endif\n      {\n# ifdef _WIN32\n        evpipe_init (EV_A);\n\n        signal (w->signum, ev_sighandler);\n# else\n        struct sigaction sa;\n\n        evpipe_init (EV_A);\n\n        sa.sa_handler = ev_sighandler;\n        sigfillset (&sa.sa_mask);\n        sa.sa_flags = SA_RESTART; /* if restarting works we save one iteration */\n        sigaction (w->signum, &sa, 0);\n\n        if (origflags & EVFLAG_NOSIGMASK)\n          {\n            sigemptyset (&sa.sa_mask);\n            sigaddset (&sa.sa_mask, w->signum);\n            sigprocmask (SIG_UNBLOCK, &sa.sa_mask, 0);\n          }\n#endif\n      }\n\n  EV_FREQUENT_CHECK;\n}\n\necb_noinline\nvoid\nev_signal_stop (EV_P_ ev_signal *w) EV_NOEXCEPT\n{\n  clear_pending (EV_A_ (W)w);\n  if (ecb_expect_false (!ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  wlist_del (&signals [w->signum - 1].head, (WL)w);\n  ev_stop (EV_A_ (W)w);\n\n  if (!signals [w->signum - 1].head)\n    {\n#if EV_MULTIPLICITY\n      signals [w->signum - 1].loop = 0; /* unattach from signal */\n#endif\n#if EV_USE_SIGNALFD\n      if (sigfd >= 0)\n        {\n          sigset_t ss;\n\n          sigemptyset (&ss);\n          sigaddset (&ss, w->signum);\n          sigdelset (&sigfd_set, w->signum);\n\n          signalfd (sigfd, &sigfd_set, 0);\n          sigprocmask (SIG_UNBLOCK, &ss, 0);\n        }\n      else\n#endif\n        signal (w->signum, SIG_DFL);\n    }\n\n  EV_FREQUENT_CHECK;\n}\n\n#endif\n\n#if EV_CHILD_ENABLE\n\nvoid\nev_child_start (EV_P_ ev_child *w) EV_NOEXCEPT\n{\n#if EV_MULTIPLICITY\n  assert ((\"libev: child watchers are only supported in the default loop\", loop == ev_default_loop_ptr));\n#endif\n  if (ecb_expect_false (ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  ev_start (EV_A_ (W)w, 1);\n  wlist_add (&childs [w->pid & ((EV_PID_HASHSIZE) - 1)], (WL)w);\n\n  EV_FREQUENT_CHECK;\n}\n\nvoid\nev_child_stop (EV_P_ ev_child *w) EV_NOEXCEPT\n{\n  clear_pending (EV_A_ (W)w);\n  if (ecb_expect_false (!ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  wlist_del (&childs [w->pid & ((EV_PID_HASHSIZE) - 1)], (WL)w);\n  ev_stop (EV_A_ (W)w);\n\n  EV_FREQUENT_CHECK;\n}\n\n#endif\n\n#if EV_STAT_ENABLE\n\n# ifdef _WIN32\n#  undef lstat\n#  define lstat(a,b) _stati64 (a,b)\n# endif\n\n#define DEF_STAT_INTERVAL  5.0074891\n#define NFS_STAT_INTERVAL 30.1074891 /* for filesystems potentially failing inotify */\n#define MIN_STAT_INTERVAL  0.1074891\n\necb_noinline static void stat_timer_cb (EV_P_ ev_timer *w_, int revents);\n\n#if EV_USE_INOTIFY\n\n/* the * 2 is to allow for alignment padding, which for some reason is >> 8 */\n# define EV_INOTIFY_BUFSIZE (sizeof (struct inotify_event) * 2 + NAME_MAX)\n\necb_noinline\nstatic void\ninfy_add (EV_P_ ev_stat *w)\n{\n  w->wd = inotify_add_watch (fs_fd, w->path,\n                             IN_ATTRIB | IN_DELETE_SELF | IN_MOVE_SELF | IN_MODIFY\n                             | IN_CREATE | IN_DELETE | IN_MOVED_FROM | IN_MOVED_TO\n                             | IN_DONT_FOLLOW | IN_MASK_ADD);\n\n  if (w->wd >= 0)\n    {\n      struct statfs sfs;\n\n      /* now local changes will be tracked by inotify, but remote changes won't */\n      /* unless the filesystem is known to be local, we therefore still poll */\n      /* also do poll on <2.6.25, but with normal frequency */\n\n      if (!fs_2625)\n        w->timer.repeat = w->interval ? w->interval : DEF_STAT_INTERVAL;\n      else if (!statfs (w->path, &sfs)\n               && (sfs.f_type == 0x1373 /* devfs */\n                   || sfs.f_type == 0x4006 /* fat */\n                   || sfs.f_type == 0x4d44 /* msdos */\n                   || sfs.f_type == 0xEF53 /* ext2/3 */\n                   || sfs.f_type == 0x72b6 /* jffs2 */\n                   || sfs.f_type == 0x858458f6 /* ramfs */\n                   || sfs.f_type == 0x5346544e /* ntfs */\n                   || sfs.f_type == 0x3153464a /* jfs */\n                   || sfs.f_type == 0x9123683e /* btrfs */\n                   || sfs.f_type == 0x52654973 /* reiser3 */\n                   || sfs.f_type == 0x01021994 /* tmpfs */\n                   || sfs.f_type == 0x58465342 /* xfs */))\n        w->timer.repeat = 0.; /* filesystem is local, kernel new enough */\n      else\n        w->timer.repeat = w->interval ? w->interval : NFS_STAT_INTERVAL; /* remote, use reduced frequency */\n    }\n  else\n    {\n      /* can't use inotify, continue to stat */\n      w->timer.repeat = w->interval ? w->interval : DEF_STAT_INTERVAL;\n\n      /* if path is not there, monitor some parent directory for speedup hints */\n      /* note that exceeding the hardcoded path limit is not a correctness issue, */\n      /* but an efficiency issue only */\n      if ((errno == ENOENT || errno == EACCES) && strlen (w->path) < 4096)\n        {\n          char path [4096];\n          strcpy (path, w->path);\n\n          do\n            {\n              int mask = IN_MASK_ADD | IN_DELETE_SELF | IN_MOVE_SELF\n                       | (errno == EACCES ? IN_ATTRIB : IN_CREATE | IN_MOVED_TO);\n\n              char *pend = strrchr (path, '/');\n\n              if (!pend || pend == path)\n                break;\n\n              *pend = 0;\n              w->wd = inotify_add_watch (fs_fd, path, mask);\n            }\n          while (w->wd < 0 && (errno == ENOENT || errno == EACCES));\n        }\n    }\n\n  if (w->wd >= 0)\n    wlist_add (&fs_hash [w->wd & ((EV_INOTIFY_HASHSIZE) - 1)].head, (WL)w);\n\n  /* now re-arm timer, if required */\n  if (ev_is_active (&w->timer)) ev_ref (EV_A);\n  ev_timer_again (EV_A_ &w->timer);\n  if (ev_is_active (&w->timer)) ev_unref (EV_A);\n}\n\necb_noinline\nstatic void\ninfy_del (EV_P_ ev_stat *w)\n{\n  int slot;\n  int wd = w->wd;\n\n  if (wd < 0)\n    return;\n\n  w->wd = -2;\n  slot = wd & ((EV_INOTIFY_HASHSIZE) - 1);\n  wlist_del (&fs_hash [slot].head, (WL)w);\n\n  /* remove this watcher, if others are watching it, they will rearm */\n  inotify_rm_watch (fs_fd, wd);\n}\n\necb_noinline\nstatic void\ninfy_wd (EV_P_ int slot, int wd, struct inotify_event *ev)\n{\n  if (slot < 0)\n    /* overflow, need to check for all hash slots */\n    for (slot = 0; slot < (EV_INOTIFY_HASHSIZE); ++slot)\n      infy_wd (EV_A_ slot, wd, ev);\n  else\n    {\n      WL w_;\n\n      for (w_ = fs_hash [slot & ((EV_INOTIFY_HASHSIZE) - 1)].head; w_; )\n        {\n          ev_stat *w = (ev_stat *)w_;\n          w_ = w_->next; /* lets us remove this watcher and all before it */\n\n          if (w->wd == wd || wd == -1)\n            {\n              if (ev->mask & (IN_IGNORED | IN_UNMOUNT | IN_DELETE_SELF))\n                {\n                  wlist_del (&fs_hash [slot & ((EV_INOTIFY_HASHSIZE) - 1)].head, (WL)w);\n                  w->wd = -1;\n                  infy_add (EV_A_ w); /* re-add, no matter what */\n                }\n\n              stat_timer_cb (EV_A_ &w->timer, 0);\n            }\n        }\n    }\n}\n\nstatic void\ninfy_cb (EV_P_ ev_io *w, int revents)\n{\n  char buf [EV_INOTIFY_BUFSIZE];\n  int ofs;\n  int len = read (fs_fd, buf, sizeof (buf));\n\n  for (ofs = 0; ofs < len; )\n    {\n      struct inotify_event *ev = (struct inotify_event *)(buf + ofs);\n      infy_wd (EV_A_ ev->wd, ev->wd, ev);\n      ofs += sizeof (struct inotify_event) + ev->len;\n    }\n}\n\ninline_size ecb_cold\nvoid\nev_check_2625 (EV_P)\n{\n  /* kernels < 2.6.25 are borked\n   * http://www.ussg.indiana.edu/hypermail/linux/kernel/0711.3/1208.html\n   */\n  if (ev_linux_version () < 0x020619)\n    return;\n\n  fs_2625 = 1;\n}\n\ninline_size int\ninfy_newfd (void)\n{\n#if defined IN_CLOEXEC && defined IN_NONBLOCK\n  int fd = inotify_init1 (IN_CLOEXEC | IN_NONBLOCK);\n  if (fd >= 0)\n    return fd;\n#endif\n  return inotify_init ();\n}\n\ninline_size void\ninfy_init (EV_P)\n{\n  if (fs_fd != -2)\n    return;\n\n  fs_fd = -1;\n\n  ev_check_2625 (EV_A);\n\n  fs_fd = infy_newfd ();\n\n  if (fs_fd >= 0)\n    {\n      fd_intern (fs_fd);\n      ev_io_init (&fs_w, infy_cb, fs_fd, EV_READ);\n      ev_set_priority (&fs_w, EV_MAXPRI);\n      ev_io_start (EV_A_ &fs_w);\n      ev_unref (EV_A);\n    }\n}\n\ninline_size void\ninfy_fork (EV_P)\n{\n  int slot;\n\n  if (fs_fd < 0)\n    return;\n\n  ev_ref (EV_A);\n  ev_io_stop (EV_A_ &fs_w);\n  close (fs_fd);\n  fs_fd = infy_newfd ();\n\n  if (fs_fd >= 0)\n    {\n      fd_intern (fs_fd);\n      ev_io_set (&fs_w, fs_fd, EV_READ);\n      ev_io_start (EV_A_ &fs_w);\n      ev_unref (EV_A);\n    }\n\n  for (slot = 0; slot < (EV_INOTIFY_HASHSIZE); ++slot)\n    {\n      WL w_ = fs_hash [slot].head;\n      fs_hash [slot].head = 0;\n\n      while (w_)\n        {\n          ev_stat *w = (ev_stat *)w_;\n          w_ = w_->next; /* lets us add this watcher */\n\n          w->wd = -1;\n\n          if (fs_fd >= 0)\n            infy_add (EV_A_ w); /* re-add, no matter what */\n          else\n            {\n              w->timer.repeat = w->interval ? w->interval : DEF_STAT_INTERVAL;\n              if (ev_is_active (&w->timer)) ev_ref (EV_A);\n              ev_timer_again (EV_A_ &w->timer);\n              if (ev_is_active (&w->timer)) ev_unref (EV_A);\n            }\n        }\n    }\n}\n\n#endif\n\n#ifdef _WIN32\n# define EV_LSTAT(p,b) _stati64 (p, b)\n#else\n# define EV_LSTAT(p,b) lstat (p, b)\n#endif\n\nvoid\nev_stat_stat (EV_P_ ev_stat *w) EV_NOEXCEPT\n{\n  if (lstat (w->path, &w->attr) < 0)\n    w->attr.st_nlink = 0;\n  else if (!w->attr.st_nlink)\n    w->attr.st_nlink = 1;\n}\n\necb_noinline\nstatic void\nstat_timer_cb (EV_P_ ev_timer *w_, int revents)\n{\n  ev_stat *w = (ev_stat *)(((char *)w_) - offsetof (ev_stat, timer));\n\n  ev_statdata prev = w->attr;\n  ev_stat_stat (EV_A_ w);\n\n  /* memcmp doesn't work on netbsd, they.... do stuff to their struct stat */\n  if (\n    prev.st_dev      != w->attr.st_dev\n    || prev.st_ino   != w->attr.st_ino\n    || prev.st_mode  != w->attr.st_mode\n    || prev.st_nlink != w->attr.st_nlink\n    || prev.st_uid   != w->attr.st_uid\n    || prev.st_gid   != w->attr.st_gid\n    || prev.st_rdev  != w->attr.st_rdev\n    || prev.st_size  != w->attr.st_size\n    || prev.st_atime != w->attr.st_atime\n    || prev.st_mtime != w->attr.st_mtime\n    || prev.st_ctime != w->attr.st_ctime\n  ) {\n      /* we only update w->prev on actual differences */\n      /* in case we test more often than invoke the callback, */\n      /* to ensure that prev is always different to attr */\n      w->prev = prev;\n\n      #if EV_USE_INOTIFY\n        if (fs_fd >= 0)\n          {\n            infy_del (EV_A_ w);\n            infy_add (EV_A_ w);\n            ev_stat_stat (EV_A_ w); /* avoid race... */\n          }\n      #endif\n\n      ev_feed_event (EV_A_ w, EV_STAT);\n    }\n}\n\nvoid\nev_stat_start (EV_P_ ev_stat *w) EV_NOEXCEPT\n{\n  if (ecb_expect_false (ev_is_active (w)))\n    return;\n\n  ev_stat_stat (EV_A_ w);\n\n  if (w->interval < MIN_STAT_INTERVAL && w->interval)\n    w->interval = MIN_STAT_INTERVAL;\n\n  ev_timer_init (&w->timer, stat_timer_cb, 0., w->interval ? w->interval : DEF_STAT_INTERVAL);\n  ev_set_priority (&w->timer, ev_priority (w));\n\n#if EV_USE_INOTIFY\n  infy_init (EV_A);\n\n  if (fs_fd >= 0)\n    infy_add (EV_A_ w);\n  else\n#endif\n    {\n      ev_timer_again (EV_A_ &w->timer);\n      ev_unref (EV_A);\n    }\n\n  ev_start (EV_A_ (W)w, 1);\n\n  EV_FREQUENT_CHECK;\n}\n\nvoid\nev_stat_stop (EV_P_ ev_stat *w) EV_NOEXCEPT\n{\n  clear_pending (EV_A_ (W)w);\n  if (ecb_expect_false (!ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n#if EV_USE_INOTIFY\n  infy_del (EV_A_ w);\n#endif\n\n  if (ev_is_active (&w->timer))\n    {\n      ev_ref (EV_A);\n      ev_timer_stop (EV_A_ &w->timer);\n    }\n\n  ev_stop (EV_A_ (W)w);\n\n  EV_FREQUENT_CHECK;\n}\n#endif\n\n#if EV_IDLE_ENABLE\nvoid\nev_idle_start (EV_P_ ev_idle *w) EV_NOEXCEPT\n{\n  if (ecb_expect_false (ev_is_active (w)))\n    return;\n\n  pri_adjust (EV_A_ (W)w);\n\n  EV_FREQUENT_CHECK;\n\n  {\n    int active = ++idlecnt [ABSPRI (w)];\n\n    ++idleall;\n    ev_start (EV_A_ (W)w, active);\n\n    array_needsize (ev_idle *, idles [ABSPRI (w)], idlemax [ABSPRI (w)], active, array_needsize_noinit);\n    idles [ABSPRI (w)][active - 1] = w;\n  }\n\n  EV_FREQUENT_CHECK;\n}\n\nvoid\nev_idle_stop (EV_P_ ev_idle *w) EV_NOEXCEPT\n{\n  clear_pending (EV_A_ (W)w);\n  if (ecb_expect_false (!ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  {\n    int active = ev_active (w);\n\n    idles [ABSPRI (w)][active - 1] = idles [ABSPRI (w)][--idlecnt [ABSPRI (w)]];\n    ev_active (idles [ABSPRI (w)][active - 1]) = active;\n\n    ev_stop (EV_A_ (W)w);\n    --idleall;\n  }\n\n  EV_FREQUENT_CHECK;\n}\n#endif\n\n#if EV_PREPARE_ENABLE\nvoid\nev_prepare_start (EV_P_ ev_prepare *w) EV_NOEXCEPT\n{\n  if (ecb_expect_false (ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  ev_start (EV_A_ (W)w, ++preparecnt);\n  array_needsize (ev_prepare *, prepares, preparemax, preparecnt, array_needsize_noinit);\n  prepares [preparecnt - 1] = w;\n\n  EV_FREQUENT_CHECK;\n}\n\nvoid\nev_prepare_stop (EV_P_ ev_prepare *w) EV_NOEXCEPT\n{\n  clear_pending (EV_A_ (W)w);\n  if (ecb_expect_false (!ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  {\n    int active = ev_active (w);\n\n    prepares [active - 1] = prepares [--preparecnt];\n    ev_active (prepares [active - 1]) = active;\n  }\n\n  ev_stop (EV_A_ (W)w);\n\n  EV_FREQUENT_CHECK;\n}\n#endif\n\n#if EV_CHECK_ENABLE\nvoid\nev_check_start (EV_P_ ev_check *w) EV_NOEXCEPT\n{\n  if (ecb_expect_false (ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  ev_start (EV_A_ (W)w, ++checkcnt);\n  array_needsize (ev_check *, checks, checkmax, checkcnt, array_needsize_noinit);\n  checks [checkcnt - 1] = w;\n\n  EV_FREQUENT_CHECK;\n}\n\nvoid\nev_check_stop (EV_P_ ev_check *w) EV_NOEXCEPT\n{\n  clear_pending (EV_A_ (W)w);\n  if (ecb_expect_false (!ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  {\n    int active = ev_active (w);\n\n    checks [active - 1] = checks [--checkcnt];\n    ev_active (checks [active - 1]) = active;\n  }\n\n  ev_stop (EV_A_ (W)w);\n\n  EV_FREQUENT_CHECK;\n}\n#endif\n\n#if EV_EMBED_ENABLE\necb_noinline\nvoid\nev_embed_sweep (EV_P_ ev_embed *w) EV_NOEXCEPT\n{\n  ev_run (w->other, EVRUN_NOWAIT);\n}\n\nstatic void\nembed_io_cb (EV_P_ ev_io *io, int revents)\n{\n  ev_embed *w = (ev_embed *)(((char *)io) - offsetof (ev_embed, io));\n\n  if (ev_cb (w))\n    ev_feed_event (EV_A_ (W)w, EV_EMBED);\n  else\n    ev_run (w->other, EVRUN_NOWAIT);\n}\n\nstatic void\nembed_prepare_cb (EV_P_ ev_prepare *prepare, int revents)\n{\n  ev_embed *w = (ev_embed *)(((char *)prepare) - offsetof (ev_embed, prepare));\n\n  {\n    EV_P = w->other;\n\n    while (fdchangecnt)\n      {\n        fd_reify (EV_A);\n        ev_run (EV_A_ EVRUN_NOWAIT);\n      }\n  }\n}\n\n#if EV_FORK_ENABLE\nstatic void\nembed_fork_cb (EV_P_ ev_fork *fork_w, int revents)\n{\n  ev_embed *w = (ev_embed *)(((char *)fork_w) - offsetof (ev_embed, fork));\n\n  ev_embed_stop (EV_A_ w);\n\n  {\n    EV_P = w->other;\n\n    ev_loop_fork (EV_A);\n    ev_run (EV_A_ EVRUN_NOWAIT);\n  }\n\n  ev_embed_start (EV_A_ w);\n}\n#endif\n\n#if 0\nstatic void\nembed_idle_cb (EV_P_ ev_idle *idle, int revents)\n{\n  ev_idle_stop (EV_A_ idle);\n}\n#endif\n\nvoid\nev_embed_start (EV_P_ ev_embed *w) EV_NOEXCEPT\n{\n  if (ecb_expect_false (ev_is_active (w)))\n    return;\n\n  {\n    EV_P = w->other;\n    assert ((\"libev: loop to be embedded is not embeddable\", backend & ev_embeddable_backends ()));\n    ev_io_init (&w->io, embed_io_cb, backend_fd, EV_READ);\n  }\n\n  EV_FREQUENT_CHECK;\n\n  ev_set_priority (&w->io, ev_priority (w));\n  ev_io_start (EV_A_ &w->io);\n\n  ev_prepare_init (&w->prepare, embed_prepare_cb);\n  ev_set_priority (&w->prepare, EV_MINPRI);\n  ev_prepare_start (EV_A_ &w->prepare);\n\n#if EV_FORK_ENABLE\n  ev_fork_init (&w->fork, embed_fork_cb);\n  ev_fork_start (EV_A_ &w->fork);\n#endif\n\n  /*ev_idle_init (&w->idle, e,bed_idle_cb);*/\n\n  ev_start (EV_A_ (W)w, 1);\n\n  EV_FREQUENT_CHECK;\n}\n\nvoid\nev_embed_stop (EV_P_ ev_embed *w) EV_NOEXCEPT\n{\n  clear_pending (EV_A_ (W)w);\n  if (ecb_expect_false (!ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  ev_io_stop      (EV_A_ &w->io);\n  ev_prepare_stop (EV_A_ &w->prepare);\n#if EV_FORK_ENABLE\n  ev_fork_stop    (EV_A_ &w->fork);\n#endif\n\n  ev_stop (EV_A_ (W)w);\n\n  EV_FREQUENT_CHECK;\n}\n#endif\n\n#if EV_FORK_ENABLE\nvoid\nev_fork_start (EV_P_ ev_fork *w) EV_NOEXCEPT\n{\n  if (ecb_expect_false (ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  ev_start (EV_A_ (W)w, ++forkcnt);\n  array_needsize (ev_fork *, forks, forkmax, forkcnt, array_needsize_noinit);\n  forks [forkcnt - 1] = w;\n\n  EV_FREQUENT_CHECK;\n}\n\nvoid\nev_fork_stop (EV_P_ ev_fork *w) EV_NOEXCEPT\n{\n  clear_pending (EV_A_ (W)w);\n  if (ecb_expect_false (!ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  {\n    int active = ev_active (w);\n\n    forks [active - 1] = forks [--forkcnt];\n    ev_active (forks [active - 1]) = active;\n  }\n\n  ev_stop (EV_A_ (W)w);\n\n  EV_FREQUENT_CHECK;\n}\n#endif\n\n#if EV_CLEANUP_ENABLE\nvoid\nev_cleanup_start (EV_P_ ev_cleanup *w) EV_NOEXCEPT\n{\n  if (ecb_expect_false (ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  ev_start (EV_A_ (W)w, ++cleanupcnt);\n  array_needsize (ev_cleanup *, cleanups, cleanupmax, cleanupcnt, array_needsize_noinit);\n  cleanups [cleanupcnt - 1] = w;\n\n  /* cleanup watchers should never keep a refcount on the loop */\n  ev_unref (EV_A);\n  EV_FREQUENT_CHECK;\n}\n\nvoid\nev_cleanup_stop (EV_P_ ev_cleanup *w) EV_NOEXCEPT\n{\n  clear_pending (EV_A_ (W)w);\n  if (ecb_expect_false (!ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n  ev_ref (EV_A);\n\n  {\n    int active = ev_active (w);\n\n    cleanups [active - 1] = cleanups [--cleanupcnt];\n    ev_active (cleanups [active - 1]) = active;\n  }\n\n  ev_stop (EV_A_ (W)w);\n\n  EV_FREQUENT_CHECK;\n}\n#endif\n\n#if EV_ASYNC_ENABLE\nvoid\nev_async_start (EV_P_ ev_async *w) EV_NOEXCEPT\n{\n  if (ecb_expect_false (ev_is_active (w)))\n    return;\n\n  w->sent = 0;\n\n  evpipe_init (EV_A);\n\n  EV_FREQUENT_CHECK;\n\n  ev_start (EV_A_ (W)w, ++asynccnt);\n  array_needsize (ev_async *, asyncs, asyncmax, asynccnt, array_needsize_noinit);\n  asyncs [asynccnt - 1] = w;\n\n  EV_FREQUENT_CHECK;\n}\n\nvoid\nev_async_stop (EV_P_ ev_async *w) EV_NOEXCEPT\n{\n  clear_pending (EV_A_ (W)w);\n  if (ecb_expect_false (!ev_is_active (w)))\n    return;\n\n  EV_FREQUENT_CHECK;\n\n  {\n    int active = ev_active (w);\n\n    asyncs [active - 1] = asyncs [--asynccnt];\n    ev_active (asyncs [active - 1]) = active;\n  }\n\n  ev_stop (EV_A_ (W)w);\n\n  EV_FREQUENT_CHECK;\n}\n\nvoid\nev_async_send (EV_P_ ev_async *w) EV_NOEXCEPT\n{\n  w->sent = 1;\n  evpipe_write (EV_A_ &async_pending);\n}\n#endif\n\n/*****************************************************************************/\n\nstruct ev_once\n{\n  ev_io io;\n  ev_timer to;\n  void (*cb)(int revents, void *arg);\n  void *arg;\n};\n\nstatic void\nonce_cb (EV_P_ struct ev_once *once, int revents)\n{\n  void (*cb)(int revents, void *arg) = once->cb;\n  void *arg = once->arg;\n\n  ev_io_stop    (EV_A_ &once->io);\n  ev_timer_stop (EV_A_ &once->to);\n  ev_free (once);\n\n  cb (revents, arg);\n}\n\nstatic void\nonce_cb_io (EV_P_ ev_io *w, int revents)\n{\n  struct ev_once *once = (struct ev_once *)(((char *)w) - offsetof (struct ev_once, io));\n\n  once_cb (EV_A_ once, revents | ev_clear_pending (EV_A_ &once->to));\n}\n\nstatic void\nonce_cb_to (EV_P_ ev_timer *w, int revents)\n{\n  struct ev_once *once = (struct ev_once *)(((char *)w) - offsetof (struct ev_once, to));\n\n  once_cb (EV_A_ once, revents | ev_clear_pending (EV_A_ &once->io));\n}\n\nvoid\nev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg) EV_NOEXCEPT\n{\n  struct ev_once *once = (struct ev_once *)ev_malloc (sizeof (struct ev_once));\n\n  once->cb  = cb;\n  once->arg = arg;\n\n  ev_init (&once->io, once_cb_io);\n  if (fd >= 0)\n    {\n      ev_io_set (&once->io, fd, events);\n      ev_io_start (EV_A_ &once->io);\n    }\n\n  ev_init (&once->to, once_cb_to);\n  if (timeout >= 0.)\n    {\n      ev_timer_set (&once->to, timeout, 0.);\n      ev_timer_start (EV_A_ &once->to);\n    }\n}\n\n/*****************************************************************************/\n\n#if EV_WALK_ENABLE\necb_cold\nvoid\nev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w)) EV_NOEXCEPT\n{\n  int i, j;\n  ev_watcher_list *wl, *wn;\n\n  if (types & (EV_IO | EV_EMBED))\n    for (i = 0; i < anfdmax; ++i)\n      for (wl = anfds [i].head; wl; )\n        {\n          wn = wl->next;\n\n#if EV_EMBED_ENABLE\n          if (ev_cb ((ev_io *)wl) == embed_io_cb)\n            {\n              if (types & EV_EMBED)\n                cb (EV_A_ EV_EMBED, ((char *)wl) - offsetof (struct ev_embed, io));\n            }\n          else\n#endif\n#if EV_USE_INOTIFY\n          if (ev_cb ((ev_io *)wl) == infy_cb)\n            ;\n          else\n#endif\n          if ((ev_io *)wl != &pipe_w)\n            if (types & EV_IO)\n              cb (EV_A_ EV_IO, wl);\n\n          wl = wn;\n        }\n\n  if (types & (EV_TIMER | EV_STAT))\n    for (i = timercnt + HEAP0; i-- > HEAP0; )\n#if EV_STAT_ENABLE\n      /*TODO: timer is not always active*/\n      if (ev_cb ((ev_timer *)ANHE_w (timers [i])) == stat_timer_cb)\n        {\n          if (types & EV_STAT)\n            cb (EV_A_ EV_STAT, ((char *)ANHE_w (timers [i])) - offsetof (struct ev_stat, timer));\n        }\n      else\n#endif\n      if (types & EV_TIMER)\n        cb (EV_A_ EV_TIMER, ANHE_w (timers [i]));\n\n#if EV_PERIODIC_ENABLE\n  if (types & EV_PERIODIC)\n    for (i = periodiccnt + HEAP0; i-- > HEAP0; )\n      cb (EV_A_ EV_PERIODIC, ANHE_w (periodics [i]));\n#endif\n\n#if EV_IDLE_ENABLE\n  if (types & EV_IDLE)\n    for (j = NUMPRI; j--; )\n      for (i = idlecnt [j]; i--; )\n        cb (EV_A_ EV_IDLE, idles [j][i]);\n#endif\n\n#if EV_FORK_ENABLE\n  if (types & EV_FORK)\n    for (i = forkcnt; i--; )\n      if (ev_cb (forks [i]) != embed_fork_cb)\n        cb (EV_A_ EV_FORK, forks [i]);\n#endif\n\n#if EV_ASYNC_ENABLE\n  if (types & EV_ASYNC)\n    for (i = asynccnt; i--; )\n      cb (EV_A_ EV_ASYNC, asyncs [i]);\n#endif\n\n#if EV_PREPARE_ENABLE\n  if (types & EV_PREPARE)\n    for (i = preparecnt; i--; )\n# if EV_EMBED_ENABLE\n      if (ev_cb (prepares [i]) != embed_prepare_cb)\n# endif\n        cb (EV_A_ EV_PREPARE, prepares [i]);\n#endif\n\n#if EV_CHECK_ENABLE\n  if (types & EV_CHECK)\n    for (i = checkcnt; i--; )\n      cb (EV_A_ EV_CHECK, checks [i]);\n#endif\n\n#if EV_SIGNAL_ENABLE\n  if (types & EV_SIGNAL)\n    for (i = 0; i < EV_NSIG - 1; ++i)\n      for (wl = signals [i].head; wl; )\n        {\n          wn = wl->next;\n          cb (EV_A_ EV_SIGNAL, wl);\n          wl = wn;\n        }\n#endif\n\n#if EV_CHILD_ENABLE\n  if (types & EV_CHILD)\n    for (i = (EV_PID_HASHSIZE); i--; )\n      for (wl = childs [i]; wl; )\n        {\n          wn = wl->next;\n          cb (EV_A_ EV_CHILD, wl);\n          wl = wn;\n        }\n#endif\n/* EV_STAT     0x00001000 /* stat data changed */\n/* EV_EMBED    0x00010000 /* embedded event loop needs sweep */\n}\n#endif\n\n#if EV_MULTIPLICITY\n  #include \"ev_wrap.h\"\n#endif\n\n"
  },
  {
    "path": "libev/ev.h",
    "content": "/*\n * libev native API header\n *\n * Copyright (c) 2007-2020 Marc Alexander Lehmann <libev@schmorp.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modifica-\n * tion, are permitted provided that the following conditions are met:\n *\n *   1.  Redistributions of source code must retain the above copyright notice,\n *       this list of conditions and the following disclaimer.\n *\n *   2.  Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-\n * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\n * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-\n * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-\n * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Alternatively, the contents of this file may be used under the terms of\n * the GNU General Public License (\"GPL\") version 2 or any later version,\n * in which case the provisions of the GPL are applicable instead of\n * the above. If you wish to allow the use of your version of this file\n * only under the terms of the GPL and not to allow others to use your\n * version of this file under the BSD license, indicate your decision\n * by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL. If you do not delete the\n * provisions above, a recipient may use your version of this file under\n * either the BSD or the GPL.\n */\n\n#ifndef EV_H_\n#define EV_H_\n\n#include \"config.h\"\n\n#ifdef __cplusplus\n# define EV_CPP(x) x\n# if __cplusplus >= 201103L\n#  define EV_NOEXCEPT noexcept\n# else\n#  define EV_NOEXCEPT\n# endif\n#else\n# define EV_CPP(x)\n# define EV_NOEXCEPT\n#endif\n#define EV_THROW EV_NOEXCEPT /* pre-4.25, do not use in new code */\n\nEV_CPP(extern \"C\" {)\n\n/*****************************************************************************/\n\n/* pre-4.0 compatibility */\n#ifndef EV_COMPAT3\n# define EV_COMPAT3 1\n#endif\n\n#ifndef EV_FEATURES\n# if defined __OPTIMIZE_SIZE__\n#  define EV_FEATURES 0x7c\n# else\n#  define EV_FEATURES 0x7f\n# endif\n#endif\n\n#define EV_FEATURE_CODE     ((EV_FEATURES) &  1)\n#define EV_FEATURE_DATA     ((EV_FEATURES) &  2)\n#define EV_FEATURE_CONFIG   ((EV_FEATURES) &  4)\n#define EV_FEATURE_API      ((EV_FEATURES) &  8)\n#define EV_FEATURE_WATCHERS ((EV_FEATURES) & 16)\n#define EV_FEATURE_BACKENDS ((EV_FEATURES) & 32)\n#define EV_FEATURE_OS       ((EV_FEATURES) & 64)\n\n/* these priorities are inclusive, higher priorities will be invoked earlier */\n#ifndef EV_MINPRI\n# define EV_MINPRI (EV_FEATURE_CONFIG ? -2 : 0)\n#endif\n#ifndef EV_MAXPRI\n# define EV_MAXPRI (EV_FEATURE_CONFIG ? +2 : 0)\n#endif\n\n#ifndef EV_MULTIPLICITY\n# define EV_MULTIPLICITY EV_FEATURE_CONFIG\n#endif\n\n#ifndef EV_PERIODIC_ENABLE\n# define EV_PERIODIC_ENABLE EV_FEATURE_WATCHERS\n#endif\n\n#ifndef EV_STAT_ENABLE\n# define EV_STAT_ENABLE EV_FEATURE_WATCHERS\n#endif\n\n#ifndef EV_PREPARE_ENABLE\n# define EV_PREPARE_ENABLE EV_FEATURE_WATCHERS\n#endif\n\n#ifndef EV_CHECK_ENABLE\n# define EV_CHECK_ENABLE EV_FEATURE_WATCHERS\n#endif\n\n#ifndef EV_IDLE_ENABLE\n# define EV_IDLE_ENABLE EV_FEATURE_WATCHERS\n#endif\n\n#ifndef EV_FORK_ENABLE\n# define EV_FORK_ENABLE EV_FEATURE_WATCHERS\n#endif\n\n#ifndef EV_CLEANUP_ENABLE\n# define EV_CLEANUP_ENABLE EV_FEATURE_WATCHERS\n#endif\n\n#ifndef EV_SIGNAL_ENABLE\n# define EV_SIGNAL_ENABLE EV_FEATURE_WATCHERS\n#endif\n\n#ifndef EV_CHILD_ENABLE\n# ifdef _WIN32\n#  define EV_CHILD_ENABLE 0\n# else\n#  define EV_CHILD_ENABLE EV_FEATURE_WATCHERS\n#endif\n#endif\n\n#ifndef EV_ASYNC_ENABLE\n# define EV_ASYNC_ENABLE EV_FEATURE_WATCHERS\n#endif\n\n#ifndef EV_EMBED_ENABLE\n# define EV_EMBED_ENABLE EV_FEATURE_WATCHERS\n#endif\n\n#ifndef EV_WALK_ENABLE\n# define EV_WALK_ENABLE 0 /* not yet */\n#endif\n\n/*****************************************************************************/\n\n#if EV_CHILD_ENABLE && !EV_SIGNAL_ENABLE\n# undef EV_SIGNAL_ENABLE\n# define EV_SIGNAL_ENABLE 1\n#endif\n\n/*****************************************************************************/\n\n#ifndef EV_TSTAMP_T\n# define EV_TSTAMP_T double\n#endif\ntypedef EV_TSTAMP_T ev_tstamp;\n\n#include <string.h> /* for memmove */\n\n#ifndef EV_ATOMIC_T\n# include <signal.h>\n# define EV_ATOMIC_T sig_atomic_t volatile\n#endif\n\n#if EV_STAT_ENABLE\n# ifdef _WIN32\n#  include <time.h>\n#  include <sys/types.h>\n# endif\n# include <sys/stat.h>\n#endif\n\n/* support multiple event loops? */\n#if EV_MULTIPLICITY\nstruct ev_loop;\n# define EV_P  struct ev_loop *loop               /* a loop as sole parameter in a declaration */\n# define EV_P_ EV_P,                              /* a loop as first of multiple parameters */\n# define EV_A  loop                               /* a loop as sole argument to a function call */\n# define EV_A_ EV_A,                              /* a loop as first of multiple arguments */\n# define EV_DEFAULT_UC  ev_default_loop_uc_ ()    /* the default loop, if initialised, as sole arg */\n# define EV_DEFAULT_UC_ EV_DEFAULT_UC,            /* the default loop as first of multiple arguments */\n# define EV_DEFAULT  ev_default_loop (0)          /* the default loop as sole arg */\n# define EV_DEFAULT_ EV_DEFAULT,                  /* the default loop as first of multiple arguments */\n#else\n# define EV_P void\n# define EV_P_\n# define EV_A\n# define EV_A_\n# define EV_DEFAULT\n# define EV_DEFAULT_\n# define EV_DEFAULT_UC\n# define EV_DEFAULT_UC_\n# undef EV_EMBED_ENABLE\n#endif\n\n/* EV_INLINE is used for functions in header files */\n#if __STDC_VERSION__ >= 199901L || __GNUC__ >= 3\n# define EV_INLINE static inline\n#else\n# define EV_INLINE static\n#endif\n\n#ifdef EV_API_STATIC\n# define EV_API_DECL static\n#else\n# define EV_API_DECL extern\n#endif\n\n/* EV_PROTOTYPES can be used to switch of prototype declarations */\n#ifndef EV_PROTOTYPES\n# define EV_PROTOTYPES 1\n#endif\n\n/*****************************************************************************/\n\n#define EV_VERSION_MAJOR 4\n#define EV_VERSION_MINOR 33\n\n/* eventmask, revents, events... */\nenum {\n  EV_UNDEF    = (int)0xFFFFFFFF, /* guaranteed to be invalid */\n  EV_NONE     =            0x00, /* no events */\n  EV_READ     =            0x01, /* ev_io detected read will not block */\n  EV_WRITE    =            0x02, /* ev_io detected write will not block */\n  EV__IOFDSET =            0x80, /* internal use only */\n  EV_IO       =         EV_READ, /* alias for type-detection */\n  EV_TIMER    =      0x00000100, /* timer timed out */\n#if EV_COMPAT3\n  EV_TIMEOUT  =        EV_TIMER, /* pre 4.0 API compatibility */\n#endif\n  EV_PERIODIC =      0x00000200, /* periodic timer timed out */\n  EV_SIGNAL   =      0x00000400, /* signal was received */\n  EV_CHILD    =      0x00000800, /* child/pid had status change */\n  EV_STAT     =      0x00001000, /* stat data changed */\n  EV_IDLE     =      0x00002000, /* event loop is idling */\n  EV_PREPARE  =      0x00004000, /* event loop about to poll */\n  EV_CHECK    =      0x00008000, /* event loop finished poll */\n  EV_EMBED    =      0x00010000, /* embedded event loop needs sweep */\n  EV_FORK     =      0x00020000, /* event loop resumed in child */\n  EV_CLEANUP  =      0x00040000, /* event loop resumed in child */\n  EV_ASYNC    =      0x00080000, /* async intra-loop signal */\n  EV_CUSTOM   =      0x01000000, /* for use by user code */\n  EV_ERROR    = (int)0x80000000  /* sent when an error occurs */\n};\n\n/* can be used to add custom fields to all watchers, while losing binary compatibility */\n#ifndef EV_COMMON\n# define EV_COMMON void *data;\n#endif\n\n#ifndef EV_CB_DECLARE\n# define EV_CB_DECLARE(type) void (*cb)(EV_P_ struct type *w, int revents);\n#endif\n#ifndef EV_CB_INVOKE\n# define EV_CB_INVOKE(watcher,revents) (watcher)->cb (EV_A_ (watcher), (revents))\n#endif\n\n/* not official, do not use */\n#define EV_CB(type,name) void name (EV_P_ struct ev_ ## type *w, int revents)\n\n/*\n * struct member types:\n * private: you may look at them, but not change them,\n *          and they might not mean anything to you.\n * ro: can be read anytime, but only changed when the watcher isn't active.\n * rw: can be read and modified anytime, even when the watcher is active.\n *\n * some internal details that might be helpful for debugging:\n *\n * active is either 0, which means the watcher is not active,\n *           or the array index of the watcher (periodics, timers)\n *           or the array index + 1 (most other watchers)\n *           or simply 1 for watchers that aren't in some array.\n * pending is either 0, in which case the watcher isn't,\n *           or the array index + 1 in the pendings array.\n */\n\n#if EV_MINPRI == EV_MAXPRI\n# define EV_DECL_PRIORITY\n#elif !defined (EV_DECL_PRIORITY)\n# define EV_DECL_PRIORITY int priority;\n#endif\n\n/* shared by all watchers */\n#define EV_WATCHER(type)\t\t\t\\\n  int active; /* private */\t\t\t\\\n  int pending; /* private */\t\t\t\\\n  EV_DECL_PRIORITY /* private */\t\t\\\n  EV_COMMON /* rw */\t\t\t\t\\\n  EV_CB_DECLARE (type) /* private */\n\n#define EV_WATCHER_LIST(type)\t\t\t\\\n  EV_WATCHER (type)\t\t\t\t\\\n  struct ev_watcher_list *next; /* private */\n\n#define EV_WATCHER_TIME(type)\t\t\t\\\n  EV_WATCHER (type)\t\t\t\t\\\n  ev_tstamp at;     /* private */\n\n/* base class, nothing to see here unless you subclass */\ntypedef struct ev_watcher\n{\n  EV_WATCHER (ev_watcher)\n} ev_watcher;\n\n/* base class, nothing to see here unless you subclass */\ntypedef struct ev_watcher_list\n{\n  EV_WATCHER_LIST (ev_watcher_list)\n} ev_watcher_list;\n\n/* base class, nothing to see here unless you subclass */\ntypedef struct ev_watcher_time\n{\n  EV_WATCHER_TIME (ev_watcher_time)\n} ev_watcher_time;\n\n/* invoked when fd is either EV_READable or EV_WRITEable */\n/* revent EV_READ, EV_WRITE */\ntypedef struct ev_io\n{\n  EV_WATCHER_LIST (ev_io)\n\n  int fd;     /* ro */\n  int events; /* ro */\n} ev_io;\n\n/* invoked after a specific time, repeatable (based on monotonic clock) */\n/* revent EV_TIMEOUT */\ntypedef struct ev_timer\n{\n  EV_WATCHER_TIME (ev_timer)\n\n  ev_tstamp repeat; /* rw */\n} ev_timer;\n\n/* invoked at some specific time, possibly repeating at regular intervals (based on UTC) */\n/* revent EV_PERIODIC */\ntypedef struct ev_periodic\n{\n  EV_WATCHER_TIME (ev_periodic)\n\n  ev_tstamp offset; /* rw */\n  ev_tstamp interval; /* rw */\n  ev_tstamp (*reschedule_cb)(struct ev_periodic *w, ev_tstamp now) EV_NOEXCEPT; /* rw */\n} ev_periodic;\n\n/* invoked when the given signal has been received */\n/* revent EV_SIGNAL */\ntypedef struct ev_signal\n{\n  EV_WATCHER_LIST (ev_signal)\n\n  int signum; /* ro */\n} ev_signal;\n\n/* invoked when sigchld is received and waitpid indicates the given pid */\n/* revent EV_CHILD */\n/* does not support priorities */\ntypedef struct ev_child\n{\n  EV_WATCHER_LIST (ev_child)\n\n  int flags;   /* private */\n  int pid;     /* ro */\n  int rpid;    /* rw, holds the received pid */\n  int rstatus; /* rw, holds the exit status, use the macros from sys/wait.h */\n} ev_child;\n\n#if EV_STAT_ENABLE\n/* st_nlink = 0 means missing file or other error */\n# ifdef _WIN32\ntypedef struct _stati64 ev_statdata;\n# else\ntypedef struct stat ev_statdata;\n# endif\n\n/* invoked each time the stat data changes for a given path */\n/* revent EV_STAT */\ntypedef struct ev_stat\n{\n  EV_WATCHER_LIST (ev_stat)\n\n  ev_timer timer;     /* private */\n  ev_tstamp interval; /* ro */\n  const char *path;   /* ro */\n  ev_statdata prev;   /* ro */\n  ev_statdata attr;   /* ro */\n\n  int wd; /* wd for inotify, fd for kqueue */\n} ev_stat;\n#endif\n\n/* invoked when the nothing else needs to be done, keeps the process from blocking */\n/* revent EV_IDLE */\ntypedef struct ev_idle\n{\n  EV_WATCHER (ev_idle)\n} ev_idle;\n\n/* invoked for each run of the mainloop, just before the blocking call */\n/* you can still change events in any way you like */\n/* revent EV_PREPARE */\ntypedef struct ev_prepare\n{\n  EV_WATCHER (ev_prepare)\n} ev_prepare;\n\n/* invoked for each run of the mainloop, just after the blocking call */\n/* revent EV_CHECK */\ntypedef struct ev_check\n{\n  EV_WATCHER (ev_check)\n} ev_check;\n\n/* the callback gets invoked before check in the child process when a fork was detected */\n/* revent EV_FORK */\ntypedef struct ev_fork\n{\n  EV_WATCHER (ev_fork)\n} ev_fork;\n\n/* is invoked just before the loop gets destroyed */\n/* revent EV_CLEANUP */\ntypedef struct ev_cleanup\n{\n  EV_WATCHER (ev_cleanup)\n} ev_cleanup;\n\n#if EV_EMBED_ENABLE\n/* used to embed an event loop inside another */\n/* the callback gets invoked when the event loop has handled events, and can be 0 */\ntypedef struct ev_embed\n{\n  EV_WATCHER (ev_embed)\n\n  struct ev_loop *other; /* ro */\n#undef EV_IO_ENABLE\n#define EV_IO_ENABLE 1\n  ev_io io;              /* private */\n#undef EV_PREPARE_ENABLE\n#define EV_PREPARE_ENABLE 1\n  ev_prepare prepare;    /* private */\n  ev_check check;        /* unused */\n  ev_timer timer;        /* unused */\n  ev_periodic periodic;  /* unused */\n  ev_idle idle;          /* unused */\n  ev_fork fork;          /* private */\n  ev_cleanup cleanup;    /* unused */\n} ev_embed;\n#endif\n\n#if EV_ASYNC_ENABLE\n/* invoked when somebody calls ev_async_send on the watcher */\n/* revent EV_ASYNC */\ntypedef struct ev_async\n{\n  EV_WATCHER (ev_async)\n\n  EV_ATOMIC_T sent; /* private */\n} ev_async;\n\n# define ev_async_pending(w) (+(w)->sent)\n#endif\n\n/* the presence of this union forces similar struct layout */\nunion ev_any_watcher\n{\n  struct ev_watcher w;\n  struct ev_watcher_list wl;\n\n  struct ev_io io;\n  struct ev_timer timer;\n  struct ev_periodic periodic;\n  struct ev_signal signal;\n  struct ev_child child;\n#if EV_STAT_ENABLE\n  struct ev_stat stat;\n#endif\n#if EV_IDLE_ENABLE\n  struct ev_idle idle;\n#endif\n  struct ev_prepare prepare;\n  struct ev_check check;\n#if EV_FORK_ENABLE\n  struct ev_fork fork;\n#endif\n#if EV_CLEANUP_ENABLE\n  struct ev_cleanup cleanup;\n#endif\n#if EV_EMBED_ENABLE\n  struct ev_embed embed;\n#endif\n#if EV_ASYNC_ENABLE\n  struct ev_async async;\n#endif\n};\n\n/* flag bits for ev_default_loop and ev_loop_new */\nenum {\n  /* the default */\n  EVFLAG_AUTO       = 0x00000000U, /* not quite a mask */\n  /* flag bits */\n  EVFLAG_NOENV      = 0x01000000U, /* do NOT consult environment */\n  EVFLAG_FORKCHECK  = 0x02000000U, /* check for a fork in each iteration */\n  /* debugging/feature disable */\n  EVFLAG_NOINOTIFY  = 0x00100000U, /* do not attempt to use inotify */\n#if EV_COMPAT3\n  EVFLAG_NOSIGFD    = 0, /* compatibility to pre-3.9 */\n#endif\n  EVFLAG_SIGNALFD   = 0x00200000U, /* attempt to use signalfd */\n  EVFLAG_NOSIGMASK  = 0x00400000U, /* avoid modifying the signal mask */\n  EVFLAG_NOTIMERFD  = 0x00800000U  /* avoid creating a timerfd */\n};\n\n/* method bits to be ored together */\nenum {\n  EVBACKEND_SELECT   = 0x00000001U, /* available just about anywhere */\n  EVBACKEND_POLL     = 0x00000002U, /* !win, !aix, broken on osx */\n  EVBACKEND_EPOLL    = 0x00000004U, /* linux */\n  EVBACKEND_KQUEUE   = 0x00000008U, /* bsd, broken on osx */\n  EVBACKEND_DEVPOLL  = 0x00000010U, /* solaris 8 */ /* NYI */\n  EVBACKEND_PORT     = 0x00000020U, /* solaris 10 */\n  EVBACKEND_LINUXAIO = 0x00000040U, /* linux AIO, 4.19+ */\n  EVBACKEND_IOURING  = 0x00000080U, /* linux io_uring, 5.1+ */\n  EVBACKEND_ALL      = 0x000000FFU, /* all known backends */\n  EVBACKEND_MASK     = 0x0000FFFFU  /* all future backends */\n};\n\n#if EV_PROTOTYPES\nEV_API_DECL int ev_version_major (void) EV_NOEXCEPT;\nEV_API_DECL int ev_version_minor (void) EV_NOEXCEPT;\n\nEV_API_DECL unsigned int ev_supported_backends (void) EV_NOEXCEPT;\nEV_API_DECL unsigned int ev_recommended_backends (void) EV_NOEXCEPT;\nEV_API_DECL unsigned int ev_embeddable_backends (void) EV_NOEXCEPT;\n\nEV_API_DECL ev_tstamp ev_time (void) EV_NOEXCEPT;\nEV_API_DECL void ev_sleep (ev_tstamp delay) EV_NOEXCEPT; /* sleep for a while */\n\n/* Sets the allocation function to use, works like realloc.\n * It is used to allocate and free memory.\n * If it returns zero when memory needs to be allocated, the library might abort\n * or take some potentially destructive action.\n * The default is your system realloc function.\n */\nEV_API_DECL void ev_set_allocator (void *(*cb)(void *ptr, long size) EV_NOEXCEPT) EV_NOEXCEPT;\n\n/* set the callback function to call on a\n * retryable syscall error\n * (such as failed select, poll, epoll_wait)\n */\nEV_API_DECL void ev_set_syserr_cb (void (*cb)(const char *msg) EV_NOEXCEPT) EV_NOEXCEPT;\n\n#if EV_MULTIPLICITY\n\n/* the default loop is the only one that handles signals and child watchers */\n/* you can call this as often as you like */\nEV_API_DECL struct ev_loop *ev_default_loop (unsigned int flags EV_CPP (= 0)) EV_NOEXCEPT;\n\n#ifdef EV_API_STATIC\nEV_API_DECL struct ev_loop *ev_default_loop_ptr;\n#endif\n\nEV_INLINE struct ev_loop *\nev_default_loop_uc_ (void) EV_NOEXCEPT\n{\n  extern struct ev_loop *ev_default_loop_ptr;\n\n  return ev_default_loop_ptr;\n}\n\nEV_INLINE int\nev_is_default_loop (EV_P) EV_NOEXCEPT\n{\n  return EV_A == EV_DEFAULT_UC;\n}\n\n/* create and destroy alternative loops that don't handle signals */\nEV_API_DECL struct ev_loop *ev_loop_new (unsigned int flags EV_CPP (= 0)) EV_NOEXCEPT;\n\nEV_API_DECL ev_tstamp ev_now (EV_P) EV_NOEXCEPT; /* time w.r.t. timers and the eventloop, updated after each poll */\n\n#else\n\nEV_API_DECL int ev_default_loop (unsigned int flags EV_CPP (= 0)) EV_NOEXCEPT; /* returns true when successful */\n\nEV_API_DECL ev_tstamp ev_rt_now;\n\nEV_INLINE ev_tstamp\nev_now (void) EV_NOEXCEPT\n{\n  return ev_rt_now;\n}\n\n/* looks weird, but ev_is_default_loop (EV_A) still works if this exists */\nEV_INLINE int\nev_is_default_loop (void) EV_NOEXCEPT\n{\n  return 1;\n}\n\n#endif /* multiplicity */\n\n/* destroy event loops, also works for the default loop */\nEV_API_DECL void ev_loop_destroy (EV_P);\n\n/* this needs to be called after fork, to duplicate the loop */\n/* when you want to re-use it in the child */\n/* you can call it in either the parent or the child */\n/* you can actually call it at any time, anywhere :) */\nEV_API_DECL void ev_loop_fork (EV_P) EV_NOEXCEPT;\n\nEV_API_DECL unsigned int ev_backend (EV_P) EV_NOEXCEPT; /* backend in use by loop */\n\nEV_API_DECL void ev_now_update (EV_P) EV_NOEXCEPT; /* update event loop time */\n\n#if EV_WALK_ENABLE\n/* walk (almost) all watchers in the loop of a given type, invoking the */\n/* callback on every such watcher. The callback might stop the watcher, */\n/* but do nothing else with the loop */\nEV_API_DECL void ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w)) EV_NOEXCEPT;\n#endif\n\n#endif /* prototypes */\n\n/* ev_run flags values */\nenum {\n  EVRUN_NOWAIT = 1, /* do not block/wait */\n  EVRUN_ONCE   = 2  /* block *once* only */\n};\n\n/* ev_break how values */\nenum {\n  EVBREAK_CANCEL = 0, /* undo unloop */\n  EVBREAK_ONE    = 1, /* unloop once */\n  EVBREAK_ALL    = 2  /* unloop all loops */\n};\n\n#if EV_PROTOTYPES\nEV_API_DECL int  ev_run (EV_P_ int flags EV_CPP (= 0));\nEV_API_DECL void ev_break (EV_P_ int how EV_CPP (= EVBREAK_ONE)) EV_NOEXCEPT; /* break out of the loop */\n\n/*\n * ref/unref can be used to add or remove a refcount on the mainloop. every watcher\n * keeps one reference. if you have a long-running watcher you never unregister that\n * should not keep ev_loop from running, unref() after starting, and ref() before stopping.\n */\nEV_API_DECL void ev_ref   (EV_P) EV_NOEXCEPT;\nEV_API_DECL void ev_unref (EV_P) EV_NOEXCEPT;\n\n/*\n * convenience function, wait for a single event, without registering an event watcher\n * if timeout is < 0, do wait indefinitely\n */\nEV_API_DECL void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg) EV_NOEXCEPT;\n\nEV_API_DECL void ev_invoke_pending (EV_P); /* invoke all pending watchers */\n\n# if EV_FEATURE_API\nEV_API_DECL unsigned int ev_iteration (EV_P) EV_NOEXCEPT; /* number of loop iterations */\nEV_API_DECL unsigned int ev_depth     (EV_P) EV_NOEXCEPT; /* #ev_loop enters - #ev_loop leaves */\nEV_API_DECL void         ev_verify    (EV_P) EV_NOEXCEPT; /* abort if loop data corrupted */\n\nEV_API_DECL void ev_set_io_collect_interval (EV_P_ ev_tstamp interval) EV_NOEXCEPT; /* sleep at least this time, default 0 */\nEV_API_DECL void ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval) EV_NOEXCEPT; /* sleep at least this time, default 0 */\n\n/* advanced stuff for threading etc. support, see docs */\nEV_API_DECL void ev_set_userdata (EV_P_ void *data) EV_NOEXCEPT;\nEV_API_DECL void *ev_userdata (EV_P) EV_NOEXCEPT;\ntypedef void (*ev_loop_callback)(EV_P);\nEV_API_DECL void ev_set_invoke_pending_cb (EV_P_ ev_loop_callback invoke_pending_cb) EV_NOEXCEPT;\n/* C++ doesn't allow the use of the ev_loop_callback typedef here, so we need to spell it out */\nEV_API_DECL void ev_set_loop_release_cb (EV_P_ void (*release)(EV_P) EV_NOEXCEPT, void (*acquire)(EV_P) EV_NOEXCEPT) EV_NOEXCEPT;\n\nEV_API_DECL unsigned int ev_pending_count (EV_P) EV_NOEXCEPT; /* number of pending events, if any */\n\n/*\n * stop/start the timer handling.\n */\nEV_API_DECL void ev_suspend (EV_P) EV_NOEXCEPT;\nEV_API_DECL void ev_resume  (EV_P) EV_NOEXCEPT;\n#endif\n\n#endif\n\n/* these may evaluate ev multiple times, and the other arguments at most once */\n/* either use ev_init + ev_TYPE_set, or the ev_TYPE_init macro, below, to first initialise a watcher */\n#define ev_init(ev,cb_) do {\t\t\t\\\n  ((ev_watcher *)(void *)(ev))->active  =\t\\\n  ((ev_watcher *)(void *)(ev))->pending = 0;\t\\\n  ev_set_priority ((ev), 0);\t\t\t\\\n  ev_set_cb ((ev), cb_);\t\t\t\\\n} while (0)\n\n#define ev_io_modify(ev,events_)             do { (ev)->events = ((ev)->events & EV__IOFDSET) | (events_); } while (0)\n#define ev_io_set(ev,fd_,events_)            do { (ev)->fd = (fd_); (ev)->events = (events_) | EV__IOFDSET; } while (0)\n#define ev_timer_set(ev,after_,repeat_)      do { ((ev_watcher_time *)(ev))->at = (after_); (ev)->repeat = (repeat_); } while (0)\n#define ev_periodic_set(ev,ofs_,ival_,rcb_)  do { (ev)->offset = (ofs_); (ev)->interval = (ival_); (ev)->reschedule_cb = (rcb_); } while (0)\n#define ev_signal_set(ev,signum_)            do { (ev)->signum = (signum_); } while (0)\n#define ev_child_set(ev,pid_,trace_)         do { (ev)->pid = (pid_); (ev)->flags = !!(trace_); } while (0)\n#define ev_stat_set(ev,path_,interval_)      do { (ev)->path = (path_); (ev)->interval = (interval_); (ev)->wd = -2; } while (0)\n#define ev_idle_set(ev)                      /* nop, yes, this is a serious in-joke */\n#define ev_prepare_set(ev)                   /* nop, yes, this is a serious in-joke */\n#define ev_check_set(ev)                     /* nop, yes, this is a serious in-joke */\n#define ev_embed_set(ev,other_)              do { (ev)->other = (other_); } while (0)\n#define ev_fork_set(ev)                      /* nop, yes, this is a serious in-joke */\n#define ev_cleanup_set(ev)                   /* nop, yes, this is a serious in-joke */\n#define ev_async_set(ev)                     /* nop, yes, this is a serious in-joke */\n\n#define ev_io_init(ev,cb,fd,events)          do { ev_init ((ev), (cb)); ev_io_set ((ev),(fd),(events)); } while (0)\n#define ev_timer_init(ev,cb,after,repeat)    do { ev_init ((ev), (cb)); ev_timer_set ((ev),(after),(repeat)); } while (0)\n#define ev_periodic_init(ev,cb,ofs,ival,rcb) do { ev_init ((ev), (cb)); ev_periodic_set ((ev),(ofs),(ival),(rcb)); } while (0)\n#define ev_signal_init(ev,cb,signum)         do { ev_init ((ev), (cb)); ev_signal_set ((ev), (signum)); } while (0)\n#define ev_child_init(ev,cb,pid,trace)       do { ev_init ((ev), (cb)); ev_child_set ((ev),(pid),(trace)); } while (0)\n#define ev_stat_init(ev,cb,path,interval)    do { ev_init ((ev), (cb)); ev_stat_set ((ev),(path),(interval)); } while (0)\n#define ev_idle_init(ev,cb)                  do { ev_init ((ev), (cb)); ev_idle_set ((ev)); } while (0)\n#define ev_prepare_init(ev,cb)               do { ev_init ((ev), (cb)); ev_prepare_set ((ev)); } while (0)\n#define ev_check_init(ev,cb)                 do { ev_init ((ev), (cb)); ev_check_set ((ev)); } while (0)\n#define ev_embed_init(ev,cb,other)           do { ev_init ((ev), (cb)); ev_embed_set ((ev),(other)); } while (0)\n#define ev_fork_init(ev,cb)                  do { ev_init ((ev), (cb)); ev_fork_set ((ev)); } while (0)\n#define ev_cleanup_init(ev,cb)               do { ev_init ((ev), (cb)); ev_cleanup_set ((ev)); } while (0)\n#define ev_async_init(ev,cb)                 do { ev_init ((ev), (cb)); ev_async_set ((ev)); } while (0)\n\n#define ev_is_pending(ev)                    (0 + ((ev_watcher *)(void *)(ev))->pending) /* ro, true when watcher is waiting for callback invocation */\n#define ev_is_active(ev)                     (0 + ((ev_watcher *)(void *)(ev))->active) /* ro, true when the watcher has been started */\n\n#define ev_cb_(ev)                           (ev)->cb /* rw */\n#define ev_cb(ev)                            (memmove (&ev_cb_ (ev), &((ev_watcher *)(ev))->cb, sizeof (ev_cb_ (ev))), (ev)->cb)\n\n#if EV_MINPRI == EV_MAXPRI\n# define ev_priority(ev)                     ((ev), EV_MINPRI)\n# define ev_set_priority(ev,pri)             ((ev), (pri))\n#else\n# define ev_priority(ev)                     (+(((ev_watcher *)(void *)(ev))->priority))\n# define ev_set_priority(ev,pri)             (   (ev_watcher *)(void *)(ev))->priority = (pri)\n#endif\n\n#define ev_periodic_at(ev)                   (+((ev_watcher_time *)(ev))->at)\n\n#ifndef ev_set_cb\n/* memmove is used here to avoid strict aliasing violations, and hopefully is optimized out by any reasonable compiler */\n# define ev_set_cb(ev,cb_)                   (ev_cb_ (ev) = (cb_), memmove (&((ev_watcher *)(ev))->cb, &ev_cb_ (ev), sizeof (ev_cb_ (ev))))\n#endif\n\n/* stopping (enabling, adding) a watcher does nothing if it is already running */\n/* stopping (disabling, deleting) a watcher does nothing unless it's already running */\n#if EV_PROTOTYPES\n\n/* feeds an event into a watcher as if the event actually occurred */\n/* accepts any ev_watcher type */\nEV_API_DECL void ev_feed_event     (EV_P_ void *w, int revents) EV_NOEXCEPT;\nEV_API_DECL void ev_feed_fd_event  (EV_P_ int fd, int revents) EV_NOEXCEPT;\n#if EV_SIGNAL_ENABLE\nEV_API_DECL void ev_feed_signal    (int signum) EV_NOEXCEPT;\nEV_API_DECL void ev_feed_signal_event (EV_P_ int signum) EV_NOEXCEPT;\n#endif\nEV_API_DECL void ev_invoke         (EV_P_ void *w, int revents);\nEV_API_DECL int  ev_clear_pending  (EV_P_ void *w) EV_NOEXCEPT;\n\nEV_API_DECL void ev_io_start       (EV_P_ ev_io *w) EV_NOEXCEPT;\nEV_API_DECL void ev_io_stop        (EV_P_ ev_io *w) EV_NOEXCEPT;\n\nEV_API_DECL void ev_timer_start    (EV_P_ ev_timer *w) EV_NOEXCEPT;\nEV_API_DECL void ev_timer_stop     (EV_P_ ev_timer *w) EV_NOEXCEPT;\n/* stops if active and no repeat, restarts if active and repeating, starts if inactive and repeating */\nEV_API_DECL void ev_timer_again    (EV_P_ ev_timer *w) EV_NOEXCEPT;\n/* return remaining time */\nEV_API_DECL ev_tstamp ev_timer_remaining (EV_P_ ev_timer *w) EV_NOEXCEPT;\n\n#if EV_PERIODIC_ENABLE\nEV_API_DECL void ev_periodic_start (EV_P_ ev_periodic *w) EV_NOEXCEPT;\nEV_API_DECL void ev_periodic_stop  (EV_P_ ev_periodic *w) EV_NOEXCEPT;\nEV_API_DECL void ev_periodic_again (EV_P_ ev_periodic *w) EV_NOEXCEPT;\n#endif\n\n/* only supported in the default loop */\n#if EV_SIGNAL_ENABLE\nEV_API_DECL void ev_signal_start   (EV_P_ ev_signal *w) EV_NOEXCEPT;\nEV_API_DECL void ev_signal_stop    (EV_P_ ev_signal *w) EV_NOEXCEPT;\n#endif\n\n/* only supported in the default loop */\n# if EV_CHILD_ENABLE\nEV_API_DECL void ev_child_start    (EV_P_ ev_child *w) EV_NOEXCEPT;\nEV_API_DECL void ev_child_stop     (EV_P_ ev_child *w) EV_NOEXCEPT;\n# endif\n\n# if EV_STAT_ENABLE\nEV_API_DECL void ev_stat_start     (EV_P_ ev_stat *w) EV_NOEXCEPT;\nEV_API_DECL void ev_stat_stop      (EV_P_ ev_stat *w) EV_NOEXCEPT;\nEV_API_DECL void ev_stat_stat      (EV_P_ ev_stat *w) EV_NOEXCEPT;\n# endif\n\n# if EV_IDLE_ENABLE\nEV_API_DECL void ev_idle_start     (EV_P_ ev_idle *w) EV_NOEXCEPT;\nEV_API_DECL void ev_idle_stop      (EV_P_ ev_idle *w) EV_NOEXCEPT;\n# endif\n\n#if EV_PREPARE_ENABLE\nEV_API_DECL void ev_prepare_start  (EV_P_ ev_prepare *w) EV_NOEXCEPT;\nEV_API_DECL void ev_prepare_stop   (EV_P_ ev_prepare *w) EV_NOEXCEPT;\n#endif\n\n#if EV_CHECK_ENABLE\nEV_API_DECL void ev_check_start    (EV_P_ ev_check *w) EV_NOEXCEPT;\nEV_API_DECL void ev_check_stop     (EV_P_ ev_check *w) EV_NOEXCEPT;\n#endif\n\n# if EV_FORK_ENABLE\nEV_API_DECL void ev_fork_start     (EV_P_ ev_fork *w) EV_NOEXCEPT;\nEV_API_DECL void ev_fork_stop      (EV_P_ ev_fork *w) EV_NOEXCEPT;\n# endif\n\n# if EV_CLEANUP_ENABLE\nEV_API_DECL void ev_cleanup_start  (EV_P_ ev_cleanup *w) EV_NOEXCEPT;\nEV_API_DECL void ev_cleanup_stop   (EV_P_ ev_cleanup *w) EV_NOEXCEPT;\n# endif\n\n# if EV_EMBED_ENABLE\n/* only supported when loop to be embedded is in fact embeddable */\nEV_API_DECL void ev_embed_start    (EV_P_ ev_embed *w) EV_NOEXCEPT;\nEV_API_DECL void ev_embed_stop     (EV_P_ ev_embed *w) EV_NOEXCEPT;\nEV_API_DECL void ev_embed_sweep    (EV_P_ ev_embed *w) EV_NOEXCEPT;\n# endif\n\n# if EV_ASYNC_ENABLE\nEV_API_DECL void ev_async_start    (EV_P_ ev_async *w) EV_NOEXCEPT;\nEV_API_DECL void ev_async_stop     (EV_P_ ev_async *w) EV_NOEXCEPT;\nEV_API_DECL void ev_async_send     (EV_P_ ev_async *w) EV_NOEXCEPT;\n# endif\n\n#if EV_COMPAT3\n  #define EVLOOP_NONBLOCK EVRUN_NOWAIT\n  #define EVLOOP_ONESHOT  EVRUN_ONCE\n  #define EVUNLOOP_CANCEL EVBREAK_CANCEL\n  #define EVUNLOOP_ONE    EVBREAK_ONE\n  #define EVUNLOOP_ALL    EVBREAK_ALL\n  #if EV_PROTOTYPES\n    EV_INLINE void ev_loop   (EV_P_ int flags) { ev_run   (EV_A_ flags); }\n    EV_INLINE void ev_unloop (EV_P_ int how  ) { ev_break (EV_A_ how  ); }\n    EV_INLINE void ev_default_destroy (void) { ev_loop_destroy (EV_DEFAULT); }\n    EV_INLINE void ev_default_fork    (void) { ev_loop_fork    (EV_DEFAULT); }\n    #if EV_FEATURE_API\n      EV_INLINE unsigned int ev_loop_count  (EV_P) { return ev_iteration  (EV_A); }\n      EV_INLINE unsigned int ev_loop_depth  (EV_P) { return ev_depth      (EV_A); }\n      EV_INLINE void         ev_loop_verify (EV_P) {        ev_verify     (EV_A); }\n    #endif\n  #endif\n#else\n  typedef struct ev_loop ev_loop;\n#endif\n\n#endif\n\nEV_CPP(})\n\n#endif\n\n"
  },
  {
    "path": "libev/ev_epoll.c",
    "content": "/*\n * libev epoll fd activity backend\n *\n * Copyright (c) 2007,2008,2009,2010,2011,2016,2017,2019 Marc Alexander Lehmann <libev@schmorp.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modifica-\n * tion, are permitted provided that the following conditions are met:\n *\n *   1.  Redistributions of source code must retain the above copyright notice,\n *       this list of conditions and the following disclaimer.\n *\n *   2.  Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-\n * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\n * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-\n * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-\n * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Alternatively, the contents of this file may be used under the terms of\n * the GNU General Public License (\"GPL\") version 2 or any later version,\n * in which case the provisions of the GPL are applicable instead of\n * the above. If you wish to allow the use of your version of this file\n * only under the terms of the GPL and not to allow others to use your\n * version of this file under the BSD license, indicate your decision\n * by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL. If you do not delete the\n * provisions above, a recipient may use your version of this file under\n * either the BSD or the GPL.\n */\n\n/*\n * general notes about epoll:\n *\n * a) epoll silently removes fds from the fd set. as nothing tells us\n *    that an fd has been removed otherwise, we have to continually\n *    \"rearm\" fds that we suspect *might* have changed (same\n *    problem with kqueue, but much less costly there).\n * b) the fact that ADD != MOD creates a lot of extra syscalls due to a)\n *    and seems not to have any advantage.\n * c) the inability to handle fork or file descriptors (think dup)\n *    limits the applicability over poll, so this is not a generic\n *    poll replacement.\n * d) epoll doesn't work the same as select with many file descriptors\n *    (such as files). while not critical, no other advanced interface\n *    seems to share this (rather non-unixy) limitation.\n * e) epoll claims to be embeddable, but in practise you never get\n *    a ready event for the epoll fd (broken: <=2.6.26, working: >=2.6.32).\n * f) epoll_ctl returning EPERM means the fd is always ready.\n *\n * lots of \"weird code\" and complication handling in this file is due\n * to these design problems with epoll, as we try very hard to avoid\n * epoll_ctl syscalls for common usage patterns and handle the breakage\n * ensuing from receiving events for closed and otherwise long gone\n * file descriptors.\n */\n\n#include <sys/epoll.h>\n\n#define EV_EMASK_EPERM 0x80\n\nstatic void\nepoll_modify (EV_P_ int fd, int oev, int nev)\n{\n  struct epoll_event ev;\n  unsigned char oldmask;\n\n  /*\n   * we handle EPOLL_CTL_DEL by ignoring it here\n   * on the assumption that the fd is gone anyways\n   * if that is wrong, we have to handle the spurious\n   * event in epoll_poll.\n   * if the fd is added again, we try to ADD it, and, if that\n   * fails, we assume it still has the same eventmask.\n   */\n  if (!nev)\n    return;\n\n  oldmask = anfds [fd].emask;\n  anfds [fd].emask = nev;\n\n  /* store the generation counter in the upper 32 bits, the fd in the lower 32 bits */\n  ev.data.u64 = (uint64_t)(uint32_t)fd\n              | ((uint64_t)(uint32_t)++anfds [fd].egen << 32);\n  ev.events   = (nev & EV_READ  ? EPOLLIN  : 0)\n              | (nev & EV_WRITE ? EPOLLOUT : 0);\n\n  if (ecb_expect_true (!epoll_ctl (backend_fd, oev && oldmask != nev ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, fd, &ev)))\n    return;\n\n  if (ecb_expect_true (errno == ENOENT))\n    {\n      /* if ENOENT then the fd went away, so try to do the right thing */\n      if (!nev)\n        goto dec_egen;\n\n      if (!epoll_ctl (backend_fd, EPOLL_CTL_ADD, fd, &ev))\n        return;\n    }\n  else if (ecb_expect_true (errno == EEXIST))\n    {\n      /* EEXIST means we ignored a previous DEL, but the fd is still active */\n      /* if the kernel mask is the same as the new mask, we assume it hasn't changed */\n      if (oldmask == nev)\n        goto dec_egen;\n\n      if (!epoll_ctl (backend_fd, EPOLL_CTL_MOD, fd, &ev))\n        return;\n    }\n  else if (ecb_expect_true (errno == EPERM))\n    {\n      /* EPERM means the fd is always ready, but epoll is too snobbish */\n      /* to handle it, unlike select or poll. */\n      anfds [fd].emask = EV_EMASK_EPERM;\n\n      /* add fd to epoll_eperms, if not already inside */\n      if (!(oldmask & EV_EMASK_EPERM))\n        {\n          array_needsize (int, epoll_eperms, epoll_epermmax, epoll_epermcnt + 1, array_needsize_noinit);\n          epoll_eperms [epoll_epermcnt++] = fd;\n        }\n\n      return;\n    }\n  else\n    assert ((\"libev: I/O watcher with invalid fd found in epoll_ctl\", errno != EBADF && errno != ELOOP && errno != EINVAL));\n\n  fd_kill (EV_A_ fd);\n\ndec_egen:\n  /* we didn't successfully call epoll_ctl, so decrement the generation counter again */\n  --anfds [fd].egen;\n}\n\nstatic void\nepoll_poll (EV_P_ ev_tstamp timeout)\n{\n  int i;\n  int eventcnt;\n\n  if (ecb_expect_false (epoll_epermcnt))\n    timeout = EV_TS_CONST (0.);\n\n  /* epoll wait times cannot be larger than (LONG_MAX - 999UL) / HZ msecs, which is below */\n  /* the default libev max wait time, however. */\n  EV_RELEASE_CB;\n  eventcnt = epoll_wait (backend_fd, epoll_events, epoll_eventmax, EV_TS_TO_MSEC (timeout));\n  EV_ACQUIRE_CB;\n\n  if (ecb_expect_false (eventcnt < 0))\n    {\n      if (errno != EINTR)\n        ev_syserr (\"(libev) epoll_wait\");\n\n      return;\n    }\n\n  for (i = 0; i < eventcnt; ++i)\n    {\n      struct epoll_event *ev = epoll_events + i;\n\n      int fd = (uint32_t)ev->data.u64; /* mask out the lower 32 bits */\n      int want = anfds [fd].events;\n      int got  = (ev->events & (EPOLLOUT | EPOLLERR | EPOLLHUP) ? EV_WRITE : 0)\n               | (ev->events & (EPOLLIN  | EPOLLERR | EPOLLHUP) ? EV_READ  : 0);\n\n      /*\n       * check for spurious notification.\n       * this only finds spurious notifications on egen updates\n       * other spurious notifications will be found by epoll_ctl, below\n       * we assume that fd is always in range, as we never shrink the anfds array\n       */\n      if (ecb_expect_false ((uint32_t)anfds [fd].egen != (uint32_t)(ev->data.u64 >> 32)))\n        {\n          /* recreate kernel state */\n          postfork |= 2;\n          continue;\n        }\n\n      if (ecb_expect_false (got & ~want))\n        {\n          anfds [fd].emask = want;\n\n          /*\n           * we received an event but are not interested in it, try mod or del\n           * this often happens because we optimistically do not unregister fds\n           * when we are no longer interested in them, but also when we get spurious\n           * notifications for fds from another process. this is partially handled\n           * above with the gencounter check (== our fd is not the event fd), and\n           * partially here, when epoll_ctl returns an error (== a child has the fd\n           * but we closed it).\n           * note: for events such as POLLHUP, where we can't know whether it refers\n           * to EV_READ or EV_WRITE, we might issue redundant EPOLL_CTL_MOD calls.\n           */\n          ev->events = (want & EV_READ  ? EPOLLIN  : 0)\n                     | (want & EV_WRITE ? EPOLLOUT : 0);\n\n          /* pre-2.6.9 kernels require a non-null pointer with EPOLL_CTL_DEL, */\n          /* which is fortunately easy to do for us. */\n          if (epoll_ctl (backend_fd, want ? EPOLL_CTL_MOD : EPOLL_CTL_DEL, fd, ev))\n            {\n              postfork |= 2; /* an error occurred, recreate kernel state */\n              continue;\n            }\n        }\n\n      fd_event (EV_A_ fd, got);\n    }\n\n  /* if the receive array was full, increase its size */\n  if (ecb_expect_false (eventcnt == epoll_eventmax))\n    {\n      ev_free (epoll_events);\n      epoll_eventmax = array_nextsize (sizeof (struct epoll_event), epoll_eventmax, epoll_eventmax + 1);\n      epoll_events = (struct epoll_event *)ev_malloc (sizeof (struct epoll_event) * epoll_eventmax);\n    }\n\n  /* now synthesize events for all fds where epoll fails, while select works... */\n  for (i = epoll_epermcnt; i--; )\n    {\n      int fd = epoll_eperms [i];\n      unsigned char events = anfds [fd].events & (EV_READ | EV_WRITE);\n\n      if (anfds [fd].emask & EV_EMASK_EPERM && events)\n        fd_event (EV_A_ fd, events);\n      else\n        {\n          epoll_eperms [i] = epoll_eperms [--epoll_epermcnt];\n          anfds [fd].emask = 0;\n        }\n    }\n}\n\nstatic int\nepoll_epoll_create (void)\n{\n  int fd;\n\n#if defined EPOLL_CLOEXEC && !defined __ANDROID__\n  fd = epoll_create1 (EPOLL_CLOEXEC);\n\n  if (fd < 0 && (errno == EINVAL || errno == ENOSYS))\n#endif\n    {\n      fd = epoll_create (256);\n\n      if (fd >= 0)\n        fcntl (fd, F_SETFD, FD_CLOEXEC);\n    }\n\n  return fd;\n}\n\ninline_size\nint\nepoll_init (EV_P_ int flags)\n{\n  if ((backend_fd = epoll_epoll_create ()) < 0)\n    return 0;\n\n  backend_mintime = EV_TS_CONST (1e-3); /* epoll does sometimes return early, this is just to avoid the worst */\n  backend_modify  = epoll_modify;\n  backend_poll    = epoll_poll;\n\n  epoll_eventmax = 64; /* initial number of events receivable per poll */\n  epoll_events = (struct epoll_event *)ev_malloc (sizeof (struct epoll_event) * epoll_eventmax);\n\n  return EVBACKEND_EPOLL;\n}\n\ninline_size\nvoid\nepoll_destroy (EV_P)\n{\n  ev_free (epoll_events);\n  array_free (epoll_eperm, EMPTY);\n}\n\necb_cold\nstatic void\nepoll_fork (EV_P)\n{\n  close (backend_fd);\n\n  while ((backend_fd = epoll_epoll_create ()) < 0)\n    ev_syserr (\"(libev) epoll_create\");\n\n  fd_rearm_all (EV_A);\n}\n\n"
  },
  {
    "path": "libev/ev_vars.h",
    "content": "/*\n * loop member variable declarations\n *\n * Copyright (c) 2007,2008,2009,2010,2011,2012,2013,2019 Marc Alexander Lehmann <libev@schmorp.de>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modifica-\n * tion, are permitted provided that the following conditions are met:\n *\n *   1.  Redistributions of source code must retain the above copyright notice,\n *       this list of conditions and the following disclaimer.\n *\n *   2.  Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-\n * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO\n * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-\n * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-\n * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Alternatively, the contents of this file may be used under the terms of\n * the GNU General Public License (\"GPL\") version 2 or any later version,\n * in which case the provisions of the GPL are applicable instead of\n * the above. If you wish to allow the use of your version of this file\n * only under the terms of the GPL and not to allow others to use your\n * version of this file under the BSD license, indicate your decision\n * by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL. If you do not delete the\n * provisions above, a recipient may use your version of this file under\n * either the BSD or the GPL.\n */\n\n#define VARx(type,name) VAR(name, type name)\n\nVARx(ev_tstamp, now_floor) /* last time we refreshed rt_time */\nVARx(ev_tstamp, mn_now)    /* monotonic clock \"now\" */\nVARx(ev_tstamp, rtmn_diff) /* difference realtime - monotonic time */\n\n/* for reverse feeding of events */\nVARx(W *, rfeeds)\nVARx(int, rfeedmax)\nVARx(int, rfeedcnt)\n\nVAR (pendings, ANPENDING *pendings [NUMPRI])\nVAR (pendingmax, int pendingmax [NUMPRI])\nVAR (pendingcnt, int pendingcnt [NUMPRI])\nVARx(int, pendingpri) /* highest priority currently pending */\nVARx(ev_prepare, pending_w) /* dummy pending watcher */\n\nVARx(ev_tstamp, io_blocktime)\nVARx(ev_tstamp, timeout_blocktime)\n\nVARx(int, backend)\nVARx(int, activecnt) /* total number of active events (\"refcount\") */\nVARx(EV_ATOMIC_T, loop_done)  /* signal by ev_break */\n\nVARx(int, backend_fd)\nVARx(ev_tstamp, backend_mintime) /* assumed typical timer resolution */\nVAR (backend_modify, void (*backend_modify)(EV_P_ int fd, int oev, int nev))\nVAR (backend_poll  , void (*backend_poll)(EV_P_ ev_tstamp timeout))\n\nVARx(ANFD *, anfds)\nVARx(int, anfdmax)\n\nVAR (evpipe, int evpipe [2])\nVARx(ev_io, pipe_w)\nVARx(EV_ATOMIC_T, pipe_write_wanted)\nVARx(EV_ATOMIC_T, pipe_write_skipped)\n\n#if !defined(_WIN32) || EV_GENWRAP\nVARx(pid_t, curpid)\n#endif\n\nVARx(char, postfork)  /* true if we need to recreate kernel state after fork */\n\n#if EV_USE_SELECT || EV_GENWRAP\nVARx(void *, vec_ri)\nVARx(void *, vec_ro)\nVARx(void *, vec_wi)\nVARx(void *, vec_wo)\n#if defined(_WIN32) || EV_GENWRAP\nVARx(void *, vec_eo)\n#endif\nVARx(int, vec_max)\n#endif\n\n#if EV_USE_POLL || EV_GENWRAP\nVARx(struct pollfd *, polls)\nVARx(int, pollmax)\nVARx(int, pollcnt)\nVARx(int *, pollidxs) /* maps fds into structure indices */\nVARx(int, pollidxmax)\n#endif\n\n#if EV_USE_EPOLL || EV_GENWRAP\nVARx(struct epoll_event *, epoll_events)\nVARx(int, epoll_eventmax)\nVARx(int *, epoll_eperms)\nVARx(int, epoll_epermcnt)\nVARx(int, epoll_epermmax)\n#endif\n\n#if EV_USE_LINUXAIO || EV_GENWRAP\nVARx(aio_context_t, linuxaio_ctx)\nVARx(int, linuxaio_iteration)\nVARx(struct aniocb **, linuxaio_iocbps)\nVARx(int, linuxaio_iocbpmax)\nVARx(struct iocb **, linuxaio_submits)\nVARx(int, linuxaio_submitcnt)\nVARx(int, linuxaio_submitmax)\nVARx(ev_io, linuxaio_epoll_w)\n#endif\n\n#if EV_USE_IOURING || EV_GENWRAP\nVARx(int, iouring_fd)\nVARx(unsigned, iouring_to_submit);\nVARx(int, iouring_entries)\nVARx(int, iouring_max_entries)\nVARx(void *, iouring_sq_ring)\nVARx(void *, iouring_cq_ring)\nVARx(void *, iouring_sqes)\nVARx(uint32_t, iouring_sq_ring_size)\nVARx(uint32_t, iouring_cq_ring_size)\nVARx(uint32_t, iouring_sqes_size)\nVARx(uint32_t, iouring_sq_head)\nVARx(uint32_t, iouring_sq_tail)\nVARx(uint32_t, iouring_sq_ring_mask)\nVARx(uint32_t, iouring_sq_ring_entries)\nVARx(uint32_t, iouring_sq_flags)\nVARx(uint32_t, iouring_sq_dropped)\nVARx(uint32_t, iouring_sq_array)\nVARx(uint32_t, iouring_cq_head)\nVARx(uint32_t, iouring_cq_tail)\nVARx(uint32_t, iouring_cq_ring_mask)\nVARx(uint32_t, iouring_cq_ring_entries)\nVARx(uint32_t, iouring_cq_overflow)\nVARx(uint32_t, iouring_cq_cqes)\nVARx(ev_tstamp, iouring_tfd_to)\nVARx(int, iouring_tfd)\nVARx(ev_io, iouring_tfd_w)\n#endif\n\n#if EV_USE_KQUEUE || EV_GENWRAP\nVARx(pid_t, kqueue_fd_pid)\nVARx(struct kevent *, kqueue_changes)\nVARx(int, kqueue_changemax)\nVARx(int, kqueue_changecnt)\nVARx(struct kevent *, kqueue_events)\nVARx(int, kqueue_eventmax)\n#endif\n\n#if EV_USE_PORT || EV_GENWRAP\nVARx(struct port_event *, port_events)\nVARx(int, port_eventmax)\n#endif\n\n#if EV_USE_IOCP || EV_GENWRAP\nVARx(HANDLE, iocp)\n#endif\n\nVARx(int *, fdchanges)\nVARx(int, fdchangemax)\nVARx(int, fdchangecnt)\n\nVARx(ANHE *, timers)\nVARx(int, timermax)\nVARx(int, timercnt)\n\n#if EV_PERIODIC_ENABLE || EV_GENWRAP\nVARx(ANHE *, periodics)\nVARx(int, periodicmax)\nVARx(int, periodiccnt)\n#endif\n\n#if EV_IDLE_ENABLE || EV_GENWRAP\nVAR (idles, ev_idle **idles [NUMPRI])\nVAR (idlemax, int idlemax [NUMPRI])\nVAR (idlecnt, int idlecnt [NUMPRI])\n#endif\nVARx(int, idleall) /* total number */\n\nVARx(struct ev_prepare **, prepares)\nVARx(int, preparemax)\nVARx(int, preparecnt)\n\nVARx(struct ev_check **, checks)\nVARx(int, checkmax)\nVARx(int, checkcnt)\n\n#if EV_FORK_ENABLE || EV_GENWRAP\nVARx(struct ev_fork **, forks)\nVARx(int, forkmax)\nVARx(int, forkcnt)\n#endif\n\n#if EV_CLEANUP_ENABLE || EV_GENWRAP\nVARx(struct ev_cleanup **, cleanups)\nVARx(int, cleanupmax)\nVARx(int, cleanupcnt)\n#endif\n\n#if EV_ASYNC_ENABLE || EV_GENWRAP\nVARx(EV_ATOMIC_T, async_pending)\nVARx(struct ev_async **, asyncs)\nVARx(int, asyncmax)\nVARx(int, asynccnt)\n#endif\n\n#if EV_USE_INOTIFY || EV_GENWRAP\nVARx(int, fs_fd)\nVARx(ev_io, fs_w)\nVARx(char, fs_2625) /* whether we are running in linux 2.6.25 or newer */\nVAR (fs_hash, ANFS fs_hash [EV_INOTIFY_HASHSIZE])\n#endif\n\nVARx(EV_ATOMIC_T, sig_pending)\n#if EV_USE_SIGNALFD || EV_GENWRAP\nVARx(int, sigfd)\nVARx(ev_io, sigfd_w)\nVARx(sigset_t, sigfd_set)\n#endif\n\n#if EV_USE_TIMERFD || EV_GENWRAP\nVARx(int, timerfd) /* timerfd for time jump detection */\nVARx(ev_io, timerfd_w)\n#endif\n\nVARx(unsigned int, origflags) /* original loop flags */\n\n#if EV_FEATURE_API || EV_GENWRAP\nVARx(unsigned int, loop_count) /* total number of loop iterations/blocks */\nVARx(unsigned int, loop_depth) /* #ev_run enters - #ev_run leaves */\n\nVARx(void *, userdata)\n/* C++ doesn't support the ev_loop_callback typedef here. stinks. */\nVAR (release_cb, void (*release_cb)(EV_P) EV_NOEXCEPT)\nVAR (acquire_cb, void (*acquire_cb)(EV_P) EV_NOEXCEPT)\nVAR (invoke_cb , ev_loop_callback invoke_cb)\n#endif\n\n#undef VARx\n\n"
  },
  {
    "path": "libev/ev_wrap.h",
    "content": "/* DO NOT EDIT, automatically generated by update_ev_wrap */\n#ifndef EV_WRAP_H\n#define EV_WRAP_H\n#define acquire_cb ((loop)->acquire_cb)\n#define activecnt ((loop)->activecnt)\n#define anfdmax ((loop)->anfdmax)\n#define anfds ((loop)->anfds)\n#define async_pending ((loop)->async_pending)\n#define asynccnt ((loop)->asynccnt)\n#define asyncmax ((loop)->asyncmax)\n#define asyncs ((loop)->asyncs)\n#define backend ((loop)->backend)\n#define backend_fd ((loop)->backend_fd)\n#define backend_mintime ((loop)->backend_mintime)\n#define backend_modify ((loop)->backend_modify)\n#define backend_poll ((loop)->backend_poll)\n#define checkcnt ((loop)->checkcnt)\n#define checkmax ((loop)->checkmax)\n#define checks ((loop)->checks)\n#define cleanupcnt ((loop)->cleanupcnt)\n#define cleanupmax ((loop)->cleanupmax)\n#define cleanups ((loop)->cleanups)\n#define curpid ((loop)->curpid)\n#define epoll_epermcnt ((loop)->epoll_epermcnt)\n#define epoll_epermmax ((loop)->epoll_epermmax)\n#define epoll_eperms ((loop)->epoll_eperms)\n#define epoll_eventmax ((loop)->epoll_eventmax)\n#define epoll_events ((loop)->epoll_events)\n#define evpipe ((loop)->evpipe)\n#define fdchangecnt ((loop)->fdchangecnt)\n#define fdchangemax ((loop)->fdchangemax)\n#define fdchanges ((loop)->fdchanges)\n#define forkcnt ((loop)->forkcnt)\n#define forkmax ((loop)->forkmax)\n#define forks ((loop)->forks)\n#define fs_2625 ((loop)->fs_2625)\n#define fs_fd ((loop)->fs_fd)\n#define fs_hash ((loop)->fs_hash)\n#define fs_w ((loop)->fs_w)\n#define idleall ((loop)->idleall)\n#define idlecnt ((loop)->idlecnt)\n#define idlemax ((loop)->idlemax)\n#define idles ((loop)->idles)\n#define invoke_cb ((loop)->invoke_cb)\n#define io_blocktime ((loop)->io_blocktime)\n#define iocp ((loop)->iocp)\n#define iouring_cq_cqes ((loop)->iouring_cq_cqes)\n#define iouring_cq_head ((loop)->iouring_cq_head)\n#define iouring_cq_overflow ((loop)->iouring_cq_overflow)\n#define iouring_cq_ring ((loop)->iouring_cq_ring)\n#define iouring_cq_ring_entries ((loop)->iouring_cq_ring_entries)\n#define iouring_cq_ring_mask ((loop)->iouring_cq_ring_mask)\n#define iouring_cq_ring_size ((loop)->iouring_cq_ring_size)\n#define iouring_cq_tail ((loop)->iouring_cq_tail)\n#define iouring_entries ((loop)->iouring_entries)\n#define iouring_fd ((loop)->iouring_fd)\n#define iouring_max_entries ((loop)->iouring_max_entries)\n#define iouring_sq_array ((loop)->iouring_sq_array)\n#define iouring_sq_dropped ((loop)->iouring_sq_dropped)\n#define iouring_sq_flags ((loop)->iouring_sq_flags)\n#define iouring_sq_head ((loop)->iouring_sq_head)\n#define iouring_sq_ring ((loop)->iouring_sq_ring)\n#define iouring_sq_ring_entries ((loop)->iouring_sq_ring_entries)\n#define iouring_sq_ring_mask ((loop)->iouring_sq_ring_mask)\n#define iouring_sq_ring_size ((loop)->iouring_sq_ring_size)\n#define iouring_sq_tail ((loop)->iouring_sq_tail)\n#define iouring_sqes ((loop)->iouring_sqes)\n#define iouring_sqes_size ((loop)->iouring_sqes_size)\n#define iouring_tfd ((loop)->iouring_tfd)\n#define iouring_tfd_to ((loop)->iouring_tfd_to)\n#define iouring_tfd_w ((loop)->iouring_tfd_w)\n#define iouring_to_submit ((loop)->iouring_to_submit)\n#define kqueue_changecnt ((loop)->kqueue_changecnt)\n#define kqueue_changemax ((loop)->kqueue_changemax)\n#define kqueue_changes ((loop)->kqueue_changes)\n#define kqueue_eventmax ((loop)->kqueue_eventmax)\n#define kqueue_events ((loop)->kqueue_events)\n#define kqueue_fd_pid ((loop)->kqueue_fd_pid)\n#define linuxaio_ctx ((loop)->linuxaio_ctx)\n#define linuxaio_epoll_w ((loop)->linuxaio_epoll_w)\n#define linuxaio_iocbpmax ((loop)->linuxaio_iocbpmax)\n#define linuxaio_iocbps ((loop)->linuxaio_iocbps)\n#define linuxaio_iteration ((loop)->linuxaio_iteration)\n#define linuxaio_submitcnt ((loop)->linuxaio_submitcnt)\n#define linuxaio_submitmax ((loop)->linuxaio_submitmax)\n#define linuxaio_submits ((loop)->linuxaio_submits)\n#define loop_count ((loop)->loop_count)\n#define loop_depth ((loop)->loop_depth)\n#define loop_done ((loop)->loop_done)\n#define mn_now ((loop)->mn_now)\n#define now_floor ((loop)->now_floor)\n#define origflags ((loop)->origflags)\n#define pending_w ((loop)->pending_w)\n#define pendingcnt ((loop)->pendingcnt)\n#define pendingmax ((loop)->pendingmax)\n#define pendingpri ((loop)->pendingpri)\n#define pendings ((loop)->pendings)\n#define periodiccnt ((loop)->periodiccnt)\n#define periodicmax ((loop)->periodicmax)\n#define periodics ((loop)->periodics)\n#define pipe_w ((loop)->pipe_w)\n#define pipe_write_skipped ((loop)->pipe_write_skipped)\n#define pipe_write_wanted ((loop)->pipe_write_wanted)\n#define pollcnt ((loop)->pollcnt)\n#define pollidxmax ((loop)->pollidxmax)\n#define pollidxs ((loop)->pollidxs)\n#define pollmax ((loop)->pollmax)\n#define polls ((loop)->polls)\n#define port_eventmax ((loop)->port_eventmax)\n#define port_events ((loop)->port_events)\n#define postfork ((loop)->postfork)\n#define preparecnt ((loop)->preparecnt)\n#define preparemax ((loop)->preparemax)\n#define prepares ((loop)->prepares)\n#define release_cb ((loop)->release_cb)\n#define rfeedcnt ((loop)->rfeedcnt)\n#define rfeedmax ((loop)->rfeedmax)\n#define rfeeds ((loop)->rfeeds)\n#define rtmn_diff ((loop)->rtmn_diff)\n#define sig_pending ((loop)->sig_pending)\n#define sigfd ((loop)->sigfd)\n#define sigfd_set ((loop)->sigfd_set)\n#define sigfd_w ((loop)->sigfd_w)\n#define timeout_blocktime ((loop)->timeout_blocktime)\n#define timercnt ((loop)->timercnt)\n#define timerfd ((loop)->timerfd)\n#define timerfd_w ((loop)->timerfd_w)\n#define timermax ((loop)->timermax)\n#define timers ((loop)->timers)\n#define userdata ((loop)->userdata)\n#define vec_eo ((loop)->vec_eo)\n#define vec_max ((loop)->vec_max)\n#define vec_ri ((loop)->vec_ri)\n#define vec_ro ((loop)->vec_ro)\n#define vec_wi ((loop)->vec_wi)\n#define vec_wo ((loop)->vec_wo)\n#else\n#undef EV_WRAP_H\n#undef acquire_cb\n#undef activecnt\n#undef anfdmax\n#undef anfds\n#undef async_pending\n#undef asynccnt\n#undef asyncmax\n#undef asyncs\n#undef backend\n#undef backend_fd\n#undef backend_mintime\n#undef backend_modify\n#undef backend_poll\n#undef checkcnt\n#undef checkmax\n#undef checks\n#undef cleanupcnt\n#undef cleanupmax\n#undef cleanups\n#undef curpid\n#undef epoll_epermcnt\n#undef epoll_epermmax\n#undef epoll_eperms\n#undef epoll_eventmax\n#undef epoll_events\n#undef evpipe\n#undef fdchangecnt\n#undef fdchangemax\n#undef fdchanges\n#undef forkcnt\n#undef forkmax\n#undef forks\n#undef fs_2625\n#undef fs_fd\n#undef fs_hash\n#undef fs_w\n#undef idleall\n#undef idlecnt\n#undef idlemax\n#undef idles\n#undef invoke_cb\n#undef io_blocktime\n#undef iocp\n#undef iouring_cq_cqes\n#undef iouring_cq_head\n#undef iouring_cq_overflow\n#undef iouring_cq_ring\n#undef iouring_cq_ring_entries\n#undef iouring_cq_ring_mask\n#undef iouring_cq_ring_size\n#undef iouring_cq_tail\n#undef iouring_entries\n#undef iouring_fd\n#undef iouring_max_entries\n#undef iouring_sq_array\n#undef iouring_sq_dropped\n#undef iouring_sq_flags\n#undef iouring_sq_head\n#undef iouring_sq_ring\n#undef iouring_sq_ring_entries\n#undef iouring_sq_ring_mask\n#undef iouring_sq_ring_size\n#undef iouring_sq_tail\n#undef iouring_sqes\n#undef iouring_sqes_size\n#undef iouring_tfd\n#undef iouring_tfd_to\n#undef iouring_tfd_w\n#undef iouring_to_submit\n#undef kqueue_changecnt\n#undef kqueue_changemax\n#undef kqueue_changes\n#undef kqueue_eventmax\n#undef kqueue_events\n#undef kqueue_fd_pid\n#undef linuxaio_ctx\n#undef linuxaio_epoll_w\n#undef linuxaio_iocbpmax\n#undef linuxaio_iocbps\n#undef linuxaio_iteration\n#undef linuxaio_submitcnt\n#undef linuxaio_submitmax\n#undef linuxaio_submits\n#undef loop_count\n#undef loop_depth\n#undef loop_done\n#undef mn_now\n#undef now_floor\n#undef origflags\n#undef pending_w\n#undef pendingcnt\n#undef pendingmax\n#undef pendingpri\n#undef pendings\n#undef periodiccnt\n#undef periodicmax\n#undef periodics\n#undef pipe_w\n#undef pipe_write_skipped\n#undef pipe_write_wanted\n#undef pollcnt\n#undef pollidxmax\n#undef pollidxs\n#undef pollmax\n#undef polls\n#undef port_eventmax\n#undef port_events\n#undef postfork\n#undef preparecnt\n#undef preparemax\n#undef prepares\n#undef release_cb\n#undef rfeedcnt\n#undef rfeedmax\n#undef rfeeds\n#undef rtmn_diff\n#undef sig_pending\n#undef sigfd\n#undef sigfd_set\n#undef sigfd_w\n#undef timeout_blocktime\n#undef timercnt\n#undef timerfd\n#undef timerfd_w\n#undef timermax\n#undef timers\n#undef userdata\n#undef vec_eo\n#undef vec_max\n#undef vec_ri\n#undef vec_ro\n#undef vec_wi\n#undef vec_wo\n#endif\n"
  }
]