diff --git a/CMakeLists.txt b/CMakeLists.txt index a829cd477..34a21d1b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -221,6 +221,7 @@ configure_file("${BUILDLIB}/config.h.in" "${BUILD_INCLUDE}/config.h" ESCAPE_QUOT #------------------------- # Sub-directories +add_subdirectory(ccan) # Libraries add_subdirectory(libibumad/src) add_subdirectory(libibumad/man) diff --git a/buildlib/config.h.in b/buildlib/config.h.in index 984d51bfa..bca737ba6 100644 --- a/buildlib/config.h.in +++ b/buildlib/config.h.in @@ -1,9 +1,17 @@ +#ifndef CONFIG_H_IN +#define CONFIG_H_IN + // FIXME: Remove this, ibverbs is included so we don't need to detect #define HAVE_IBV_DOFORK_RANGE 1 #define HAVE_IBV_DONTFORK_RANGE 1 #define HAVE_IBV_REGISTER_DRIVER 1 #define HAVE_IBV_READ_SYSFS_FILE 1 +#define HAVE_STATEMENT_EXPR 1 +#define HAVE_BUILTIN_TYPES_COMPATIBLE_P 1 +#define HAVE_TYPEOF 1 +#define HAVE_ISBLANK 1 + // FIXME: Remove this, we provide the netlink kernel headers ibacm needs #define HAVE_NETLINK 1 @@ -33,3 +41,5 @@ #elif @NL_KIND@ == 0 # define NRESOLVE_NEIGH 1 #endif + +#endif diff --git a/buildlib/publish_headers.cmake b/buildlib/publish_headers.cmake index ccd22960c..c1909d677 100644 --- a/buildlib/publish_headers.cmake +++ b/buildlib/publish_headers.cmake @@ -1,10 +1,9 @@ # COPYRIGHT (c) 2016 Obsidian Research Corporation. See COPYING file -# Copy headers from the source directory to the proper place in the -# build/include directory -function(PUBLISH_HEADERS DEST) +# Same as publish_headers but does not install them during the install phase +function(publish_internal_headers DEST) if(NOT ARGN) - message(SEND_ERROR "Error: PUBLISH_HEADERS called without any files") + message(SEND_ERROR "Error: publish_internal_headers called without any files") return() endif() @@ -15,6 +14,17 @@ function(PUBLISH_HEADERS DEST) get_filename_component(FIL ${SFIL} NAME) execute_process(COMMAND "ln" "-Tsf" "${CMAKE_CURRENT_SOURCE_DIR}/${SFIL}" "${DDIR}/${FIL}") + endforeach() +endfunction() + +# Copy headers from the source directory to the proper place in the +# build/include directory. This also installs them into /usr/include/xx during +# the install phase +function(publish_headers DEST) + publish_internal_headers("${DEST}" ${ARGN}) + + foreach(SFIL ${ARGN}) + get_filename_component(FIL ${SFIL} NAME) install(FILES "${SFIL}" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${DEST}/" RENAME "${FIL}") endforeach() endfunction() diff --git a/buildlib/rdma_functions.cmake b/buildlib/rdma_functions.cmake index ea53f3825..5a1041f30 100644 --- a/buildlib/rdma_functions.cmake +++ b/buildlib/rdma_functions.cmake @@ -6,6 +6,9 @@ # Global list of pairs of (SHARED STATIC) libary target names set(RDMA_STATIC_LIBS "" CACHE INTERNAL "Doc" FORCE) +set(COMMON_LIBS_PIC ccan_pic) +set(COMMON_LIBS ccan) + # Install a symlink during 'make install' function(rdma_install_symlink LINK_CONTENT DEST) # Create a link in the build tree with the right content @@ -59,6 +62,7 @@ function(rdma_library DEST VERSION_SCRIPT SOVERSION VERSION) # Create a shared library add_library(${DEST} SHARED ${ARGN}) rdma_set_library_map(${DEST} ${VERSION_SCRIPT}) + target_link_libraries(${DEST} LINK_PRIVATE ${COMMON_LIBS_PIC}) set_target_properties(${DEST} PROPERTIES SOVERSION ${SOVERSION} VERSION ${VERSION} @@ -98,6 +102,7 @@ function(rdma_provider DEST) # Even though these are modules we still want to use Wl,--no-undefined set_target_properties(${DEST} PROPERTIES LINK_FLAGS ${CMAKE_SHARED_LINKER_FLAGS}) rdma_set_library_map(${DEST} ${BUILDLIB}/provider.map) + target_link_libraries(${DEST} LINK_PRIVATE ${COMMON_LIBS_PIC}) target_link_libraries(${DEST} LINK_PRIVATE ibverbs) target_link_libraries(${DEST} LINK_PRIVATE ${CMAKE_THREAD_LIBS_INIT}) set_target_properties(${DEST} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${BUILD_LIB}") @@ -110,6 +115,7 @@ endfunction() # Create an installed executable function(rdma_executable EXEC) add_executable(${EXEC} ${ARGN}) + target_link_libraries(${EXEC} LINK_PRIVATE ${COMMON_LIBS}) set_target_properties(${EXEC} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BUILD_BIN}") install(TARGETS ${EXEC} DESTINATION "${CMAKE_INSTALL_BINDIR}") endfunction() @@ -117,6 +123,7 @@ endfunction() # Create an installed executable (under sbin) function(rdma_sbin_executable EXEC) add_executable(${EXEC} ${ARGN}) + target_link_libraries(${EXEC} LINK_PRIVATE ${COMMON_LIBS}) set_target_properties(${EXEC} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BUILD_BIN}") install(TARGETS ${EXEC} DESTINATION "${CMAKE_INSTALL_SBINDIR}") endfunction() @@ -124,6 +131,7 @@ endfunction() # Create an test executable (not-installed) function(rdma_test_executable EXEC) add_executable(${EXEC} ${ARGN}) + target_link_libraries(${EXEC} LINK_PRIVATE ${COMMON_LIBS}) set_target_properties(${EXEC} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BUILD_BIN}") endfunction() diff --git a/ccan/BSD-MIT b/ccan/BSD-MIT new file mode 100644 index 000000000..89de35479 --- /dev/null +++ b/ccan/BSD-MIT @@ -0,0 +1,17 @@ +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/ccan/CC0 b/ccan/CC0 new file mode 100644 index 000000000..57f2f1b08 --- /dev/null +++ b/ccan/CC0 @@ -0,0 +1,97 @@ +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific works +("Commons") that the public can reliably and without fear of later claims of +infringement build upon, modify, incorporate in other works, reuse and +redistribute as freely as possible in any form whatsoever and for any purposes, +including without limitation commercial purposes. These owners may contribute +to the Commons to promote the ideal of a free culture and the further +production of creative, cultural and scientific works, or to gain reputation or +greater distribution for their Work in part through the use and efforts of +others. + +For these and/or other purposes and motivations, and without any expectation of +additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and +publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited to, +the following: + + the right to reproduce, adapt, distribute, perform, display, communicate, +and translate a Work; moral rights retained by the original author(s) and/or +performer(s); publicity and privacy rights pertaining to a person's image or +likeness depicted in a Work; rights protecting against unfair competition in +regards to a Work, subject to the limitations in paragraph 4(a), below; rights +protecting the extraction, dissemination, use and reuse of data in a Work; +database rights (such as those arising under Directive 96/9/EC of the European +Parliament and of the Council of 11 March 1996 on the legal protection of +databases, and under any national implementation thereof, including any amended +or successor version of such directive); and other similar, equivalent or +corresponding rights throughout the world based on applicable law or treaty, +and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, non +transferable, non sublicensable, non exclusive, irrevocable and unconditional +license to exercise Affirmer's Copyright and Related Rights in the Work (i) in +all territories worldwide, (ii) for the maximum duration provided by applicable +law or treaty (including future time extensions), (iii) in any current or +future medium and for any number of copies, and (iv) for any purpose +whatsoever, including without limitation commercial, advertising or promotional +purposes (the "License"). The License shall be deemed effective as of the date +CC0 was applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder of the +License, and in such case Affirmer hereby affirms that he or she will not (i) +exercise any of his or her remaining Copyright and Related Rights in the Work +or (ii) assert any associated claims and causes of action with respect to the +Work, in either case contrary to Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + No trademark or patent rights held by Affirmer are waived, abandoned, +surrendered, licensed or otherwise affected by this document. Affirmer offers +the Work as-is and makes no representations or warranties of any kind +concerning the Work, express, implied, statutory or otherwise, including +without limitation warranties of title, merchantability, fitness for a +particular purpose, non infringement, or the absence of latent or other +defects, accuracy, or the present or absence of errors, whether or not +discoverable, all to the greatest extent permissible under applicable law. +Affirmer disclaims responsibility for clearing rights of other persons that may +apply to the Work or any use thereof, including without limitation any person's +Copyright and Related Rights in the Work. Further, Affirmer disclaims +responsibility for obtaining any necessary consents, permissions or other +rights required for any use of the Work. Affirmer understands and acknowledges +that Creative Commons is not a party to this document and has no duty or +obligation with respect to this CC0 or use of the Work. diff --git a/ccan/CMakeLists.txt b/ccan/CMakeLists.txt new file mode 100644 index 000000000..505e0269d --- /dev/null +++ b/ccan/CMakeLists.txt @@ -0,0 +1,16 @@ +publish_internal_headers(ccan + build_assert.h + check_type.h + container_of.h + list.h + minmax.h + str.h + str_debug.h + ) + +set(C_FILES + str.c + ) +add_library(ccan STATIC ${C_FILES}) +add_library(ccan_pic STATIC ${C_FILES}) +set_property(TARGET ccan_pic PROPERTY POSITION_INDEPENDENT_CODE TRUE) diff --git a/ccan/build_assert.h b/ccan/build_assert.h new file mode 100644 index 000000000..b9ecd8402 --- /dev/null +++ b/ccan/build_assert.h @@ -0,0 +1,40 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#ifndef CCAN_BUILD_ASSERT_H +#define CCAN_BUILD_ASSERT_H + +/** + * BUILD_ASSERT - assert a build-time dependency. + * @cond: the compile-time condition which must be true. + * + * Your compile will fail if the condition isn't true, or can't be evaluated + * by the compiler. This can only be used within a function. + * + * Example: + * #include + * ... + * static char *foo_to_char(struct foo *foo) + * { + * // This code needs string to be at start of foo. + * BUILD_ASSERT(offsetof(struct foo, string) == 0); + * return (char *)foo; + * } + */ +#define BUILD_ASSERT(cond) \ + do { (void) sizeof(char [1 - 2*!(cond)]); } while(0) + +/** + * BUILD_ASSERT_OR_ZERO - assert a build-time dependency, as an expression. + * @cond: the compile-time condition which must be true. + * + * Your compile will fail if the condition isn't true, or can't be evaluated + * by the compiler. This can be used in an expression: its value is "0". + * + * Example: + * #define foo_to_char(foo) \ + * ((char *)(foo) \ + * + BUILD_ASSERT_OR_ZERO(offsetof(struct foo, string) == 0)) + */ +#define BUILD_ASSERT_OR_ZERO(cond) \ + (sizeof(char [1 - 2*!(cond)]) - 1) + +#endif /* CCAN_BUILD_ASSERT_H */ diff --git a/ccan/check_type.h b/ccan/check_type.h new file mode 100644 index 000000000..77501a955 --- /dev/null +++ b/ccan/check_type.h @@ -0,0 +1,64 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#ifndef CCAN_CHECK_TYPE_H +#define CCAN_CHECK_TYPE_H +#include "config.h" + +/** + * check_type - issue a warning or build failure if type is not correct. + * @expr: the expression whose type we should check (not evaluated). + * @type: the exact type we expect the expression to be. + * + * This macro is usually used within other macros to try to ensure that a macro + * argument is of the expected type. No type promotion of the expression is + * done: an unsigned int is not the same as an int! + * + * check_type() always evaluates to 0. + * + * If your compiler does not support typeof, then the best we can do is fail + * to compile if the sizes of the types are unequal (a less complete check). + * + * Example: + * // They should always pass a 64-bit value to _set_some_value! + * #define set_some_value(expr) \ + * _set_some_value((check_type((expr), uint64_t), (expr))) + */ + +/** + * check_types_match - issue a warning or build failure if types are not same. + * @expr1: the first expression (not evaluated). + * @expr2: the second expression (not evaluated). + * + * This macro is usually used within other macros to try to ensure that + * arguments are of identical types. No type promotion of the expressions is + * done: an unsigned int is not the same as an int! + * + * check_types_match() always evaluates to 0. + * + * If your compiler does not support typeof, then the best we can do is fail + * to compile if the sizes of the types are unequal (a less complete check). + * + * Example: + * // Do subtraction to get to enclosing type, but make sure that + * // pointer is of correct type for that member. + * #define container_of(mbr_ptr, encl_type, mbr) \ + * (check_types_match((mbr_ptr), &((encl_type *)0)->mbr), \ + * ((encl_type *) \ + * ((char *)(mbr_ptr) - offsetof(enclosing_type, mbr)))) + */ +#if HAVE_TYPEOF +#define check_type(expr, type) \ + ((typeof(expr) *)0 != (type *)0) + +#define check_types_match(expr1, expr2) \ + ((typeof(expr1) *)0 != (typeof(expr2) *)0) +#else +#include +/* Without typeof, we can only test the sizes. */ +#define check_type(expr, type) \ + BUILD_ASSERT_OR_ZERO(sizeof(expr) == sizeof(type)) + +#define check_types_match(expr1, expr2) \ + BUILD_ASSERT_OR_ZERO(sizeof(expr1) == sizeof(expr2)) +#endif /* HAVE_TYPEOF */ + +#endif /* CCAN_CHECK_TYPE_H */ diff --git a/ccan/container_of.h b/ccan/container_of.h new file mode 100644 index 000000000..c91b909f6 --- /dev/null +++ b/ccan/container_of.h @@ -0,0 +1,146 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#ifndef CCAN_CONTAINER_OF_H +#define CCAN_CONTAINER_OF_H +#include + +#include "config.h" +#include + +/** + * container_of - get pointer to enclosing structure + * @member_ptr: pointer to the structure member + * @containing_type: the type this member is within + * @member: the name of this member within the structure. + * + * Given a pointer to a member of a structure, this macro does pointer + * subtraction to return the pointer to the enclosing type. + * + * Example: + * struct foo { + * int fielda, fieldb; + * // ... + * }; + * struct info { + * int some_other_field; + * struct foo my_foo; + * }; + * + * static struct info *foo_to_info(struct foo *foo) + * { + * return container_of(foo, struct info, my_foo); + * } + */ +#ifndef container_of +#define container_of(member_ptr, containing_type, member) \ + ((containing_type *) \ + ((char *)(member_ptr) \ + - container_off(containing_type, member)) \ + + check_types_match(*(member_ptr), ((containing_type *)0)->member)) +#endif + +/** + * container_of_or_null - get pointer to enclosing structure, or NULL + * @member_ptr: pointer to the structure member + * @containing_type: the type this member is within + * @member: the name of this member within the structure. + * + * Given a pointer to a member of a structure, this macro does pointer + * subtraction to return the pointer to the enclosing type, unless it + * is given NULL, in which case it also returns NULL. + * + * Example: + * struct foo { + * int fielda, fieldb; + * // ... + * }; + * struct info { + * int some_other_field; + * struct foo my_foo; + * }; + * + * static struct info *foo_to_info_allowing_null(struct foo *foo) + * { + * return container_of_or_null(foo, struct info, my_foo); + * } + */ +static inline char *container_of_or_null_(void *member_ptr, size_t offset) +{ + return member_ptr ? (char *)member_ptr - offset : NULL; +} +#define container_of_or_null(member_ptr, containing_type, member) \ + ((containing_type *) \ + container_of_or_null_(member_ptr, \ + container_off(containing_type, member)) \ + + check_types_match(*(member_ptr), ((containing_type *)0)->member)) + +/** + * container_off - get offset to enclosing structure + * @containing_type: the type this member is within + * @member: the name of this member within the structure. + * + * Given a pointer to a member of a structure, this macro does + * typechecking and figures out the offset to the enclosing type. + * + * Example: + * struct foo { + * int fielda, fieldb; + * // ... + * }; + * struct info { + * int some_other_field; + * struct foo my_foo; + * }; + * + * static struct info *foo_to_info(struct foo *foo) + * { + * size_t off = container_off(struct info, my_foo); + * return (void *)((char *)foo - off); + * } + */ +#define container_off(containing_type, member) \ + offsetof(containing_type, member) + +/** + * container_of_var - get pointer to enclosing structure using a variable + * @member_ptr: pointer to the structure member + * @container_var: a pointer of same type as this member's container + * @member: the name of this member within the structure. + * + * Given a pointer to a member of a structure, this macro does pointer + * subtraction to return the pointer to the enclosing type. + * + * Example: + * static struct info *foo_to_i(struct foo *foo) + * { + * struct info *i = container_of_var(foo, i, my_foo); + * return i; + * } + */ +#if HAVE_TYPEOF +#define container_of_var(member_ptr, container_var, member) \ + container_of(member_ptr, typeof(*container_var), member) +#else +#define container_of_var(member_ptr, container_var, member) \ + ((void *)((char *)(member_ptr) - \ + container_off_var(container_var, member))) +#endif + +/** + * container_off_var - get offset of a field in enclosing structure + * @container_var: a pointer to a container structure + * @member: the name of a member within the structure. + * + * Given (any) pointer to a structure and a its member name, this + * macro does pointer subtraction to return offset of member in a + * structure memory layout. + * + */ +#if HAVE_TYPEOF +#define container_off_var(var, member) \ + container_off(typeof(*var), member) +#else +#define container_off_var(var, member) \ + ((const char *)&(var)->member - (const char *)(var)) +#endif + +#endif /* CCAN_CONTAINER_OF_H */ diff --git a/ccan/list.h b/ccan/list.h new file mode 100644 index 000000000..5bc93ffff --- /dev/null +++ b/ccan/list.h @@ -0,0 +1,842 @@ +/* Licensed under BSD-MIT - see LICENSE file for details */ +#ifndef CCAN_LIST_H +#define CCAN_LIST_H +//#define CCAN_LIST_DEBUG 1 +#include +#include +#include +#include +#include + +/** + * struct list_node - an entry in a doubly-linked list + * @next: next entry (self if empty) + * @prev: previous entry (self if empty) + * + * This is used as an entry in a linked list. + * Example: + * struct child { + * const char *name; + * // Linked list of all us children. + * struct list_node list; + * }; + */ +struct list_node +{ + struct list_node *next, *prev; +}; + +/** + * struct list_head - the head of a doubly-linked list + * @h: the list_head (containing next and prev pointers) + * + * This is used as the head of a linked list. + * Example: + * struct parent { + * const char *name; + * struct list_head children; + * unsigned int num_children; + * }; + */ +struct list_head +{ + struct list_node n; +}; + +/** + * list_check - check head of a list for consistency + * @h: the list_head + * @abortstr: the location to print on aborting, or NULL. + * + * Because list_nodes have redundant information, consistency checking between + * the back and forward links can be done. This is useful as a debugging check. + * If @abortstr is non-NULL, that will be printed in a diagnostic if the list + * is inconsistent, and the function will abort. + * + * Returns the list head if the list is consistent, NULL if not (it + * can never return NULL if @abortstr is set). + * + * See also: list_check_node() + * + * Example: + * static void dump_parent(struct parent *p) + * { + * struct child *c; + * + * printf("%s (%u children):\n", p->name, p->num_children); + * list_check(&p->children, "bad child list"); + * list_for_each(&p->children, c, list) + * printf(" -> %s\n", c->name); + * } + */ +struct list_head *list_check(const struct list_head *h, const char *abortstr); + +/** + * list_check_node - check node of a list for consistency + * @n: the list_node + * @abortstr: the location to print on aborting, or NULL. + * + * Check consistency of the list node is in (it must be in one). + * + * See also: list_check() + * + * Example: + * static void dump_child(const struct child *c) + * { + * list_check_node(&c->list, "bad child list"); + * printf("%s\n", c->name); + * } + */ +struct list_node *list_check_node(const struct list_node *n, + const char *abortstr); + +#define LIST_LOC __FILE__ ":" stringify(__LINE__) +#ifdef CCAN_LIST_DEBUG +#define list_debug(h, loc) list_check((h), loc) +#define list_debug_node(n, loc) list_check_node((n), loc) +#else +#define list_debug(h, loc) ((void)loc, h) +#define list_debug_node(n, loc) ((void)loc, n) +#endif + +/** + * LIST_HEAD_INIT - initializer for an empty list_head + * @name: the name of the list. + * + * Explicit initializer for an empty list. + * + * See also: + * LIST_HEAD, list_head_init() + * + * Example: + * static struct list_head my_list = LIST_HEAD_INIT(my_list); + */ +#define LIST_HEAD_INIT(name) { { &(name).n, &(name).n } } + +/** + * LIST_HEAD - define and initialize an empty list_head + * @name: the name of the list. + * + * The LIST_HEAD macro defines a list_head and initializes it to an empty + * list. It can be prepended by "static" to define a static list_head. + * + * See also: + * LIST_HEAD_INIT, list_head_init() + * + * Example: + * static LIST_HEAD(my_global_list); + */ +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +/** + * list_head_init - initialize a list_head + * @h: the list_head to set to the empty list + * + * Example: + * ... + * struct parent *parent = malloc(sizeof(*parent)); + * + * list_head_init(&parent->children); + * parent->num_children = 0; + */ +static inline void list_head_init(struct list_head *h) +{ + h->n.next = h->n.prev = &h->n; +} + +/** + * list_node_init - initialize a list_node + * @n: the list_node to link to itself. + * + * You don't need to use this normally! But it lets you list_del(@n) + * safely. + */ +static inline void list_node_init(struct list_node *n) +{ + n->next = n->prev = n; +} + +/** + * list_add_after - add an entry after an existing node in a linked list + * @h: the list_head to add the node to (for debugging) + * @p: the existing list_node to add the node after + * @n: the new list_node to add to the list. + * + * The existing list_node must already be a member of the list. + * The new list_node does not need to be initialized; it will be overwritten. + * + * Example: + * struct child c1, c2, c3; + * LIST_HEAD(h); + * + * list_add_tail(&h, &c1.list); + * list_add_tail(&h, &c3.list); + * list_add_after(&h, &c1.list, &c2.list); + */ +#define list_add_after(h, p, n) list_add_after_(h, p, n, LIST_LOC) +static inline void list_add_after_(struct list_head *h, + struct list_node *p, + struct list_node *n, + const char *abortstr) +{ + n->next = p->next; + n->prev = p; + p->next->prev = n; + p->next = n; + (void)list_debug(h, abortstr); +} + +/** + * list_add - add an entry at the start of a linked list. + * @h: the list_head to add the node to + * @n: the list_node to add to the list. + * + * The list_node does not need to be initialized; it will be overwritten. + * Example: + * struct child *child = malloc(sizeof(*child)); + * + * child->name = "marvin"; + * list_add(&parent->children, &child->list); + * parent->num_children++; + */ +#define list_add(h, n) list_add_(h, n, LIST_LOC) +static inline void list_add_(struct list_head *h, + struct list_node *n, + const char *abortstr) +{ + list_add_after_(h, &h->n, n, abortstr); +} + +/** + * list_add_before - add an entry before an existing node in a linked list + * @h: the list_head to add the node to (for debugging) + * @p: the existing list_node to add the node before + * @n: the new list_node to add to the list. + * + * The existing list_node must already be a member of the list. + * The new list_node does not need to be initialized; it will be overwritten. + * + * Example: + * list_head_init(&h); + * list_add_tail(&h, &c1.list); + * list_add_tail(&h, &c3.list); + * list_add_before(&h, &c3.list, &c2.list); + */ +#define list_add_before(h, p, n) list_add_before_(h, p, n, LIST_LOC) +static inline void list_add_before_(struct list_head *h, + struct list_node *p, + struct list_node *n, + const char *abortstr) +{ + n->next = p; + n->prev = p->prev; + p->prev->next = n; + p->prev = n; + (void)list_debug(h, abortstr); +} + +/** + * list_add_tail - add an entry at the end of a linked list. + * @h: the list_head to add the node to + * @n: the list_node to add to the list. + * + * The list_node does not need to be initialized; it will be overwritten. + * Example: + * list_add_tail(&parent->children, &child->list); + * parent->num_children++; + */ +#define list_add_tail(h, n) list_add_tail_(h, n, LIST_LOC) +static inline void list_add_tail_(struct list_head *h, + struct list_node *n, + const char *abortstr) +{ + list_add_before_(h, &h->n, n, abortstr); +} + +/** + * list_empty - is a list empty? + * @h: the list_head + * + * If the list is empty, returns true. + * + * Example: + * assert(list_empty(&parent->children) == (parent->num_children == 0)); + */ +#define list_empty(h) list_empty_(h, LIST_LOC) +static inline bool list_empty_(const struct list_head *h, const char* abortstr) +{ + (void)list_debug(h, abortstr); + return h->n.next == &h->n; +} + +/** + * list_empty_nodebug - is a list empty (and don't perform debug checks)? + * @h: the list_head + * + * If the list is empty, returns true. + * This differs from list_empty() in that if CCAN_LIST_DEBUG is set it + * will NOT perform debug checks. Only use this function if you REALLY + * know what you're doing. + * + * Example: + * assert(list_empty_nodebug(&parent->children) == (parent->num_children == 0)); + */ +#ifndef CCAN_LIST_DEBUG +#define list_empty_nodebug(h) list_empty(h) +#else +static inline bool list_empty_nodebug(const struct list_head *h) +{ + return h->n.next == &h->n; +} +#endif + +/** + * list_empty_nocheck - is a list empty? + * @h: the list_head + * + * If the list is empty, returns true. This doesn't perform any + * debug check for list consistency, so it can be called without + * locks, racing with the list being modified. This is ok for + * checks where an incorrect result is not an issue (optimized + * bail out path for example). + */ +static inline bool list_empty_nocheck(const struct list_head *h) +{ + return h->n.next == &h->n; +} + +/** + * list_del - delete an entry from an (unknown) linked list. + * @n: the list_node to delete from the list. + * + * Note that this leaves @n in an undefined state; it can be added to + * another list, but not deleted again. + * + * See also: + * list_del_from(), list_del_init() + * + * Example: + * list_del(&child->list); + * parent->num_children--; + */ +#define list_del(n) list_del_(n, LIST_LOC) +static inline void list_del_(struct list_node *n, const char* abortstr) +{ + (void)list_debug_node(n, abortstr); + n->next->prev = n->prev; + n->prev->next = n->next; +#ifdef CCAN_LIST_DEBUG + /* Catch use-after-del. */ + n->next = n->prev = NULL; +#endif +} + +/** + * list_del_init - delete a node, and reset it so it can be deleted again. + * @n: the list_node to be deleted. + * + * list_del(@n) or list_del_init() again after this will be safe, + * which can be useful in some cases. + * + * See also: + * list_del_from(), list_del() + * + * Example: + * list_del_init(&child->list); + * parent->num_children--; + */ +#define list_del_init(n) list_del_init_(n, LIST_LOC) +static inline void list_del_init_(struct list_node *n, const char *abortstr) +{ + list_del_(n, abortstr); + list_node_init(n); +} + +/** + * list_del_from - delete an entry from a known linked list. + * @h: the list_head the node is in. + * @n: the list_node to delete from the list. + * + * This explicitly indicates which list a node is expected to be in, + * which is better documentation and can catch more bugs. + * + * See also: list_del() + * + * Example: + * list_del_from(&parent->children, &child->list); + * parent->num_children--; + */ +static inline void list_del_from(struct list_head *h, struct list_node *n) +{ +#ifdef CCAN_LIST_DEBUG + { + /* Thorough check: make sure it was in list! */ + struct list_node *i; + for (i = h->n.next; i != n; i = i->next) + assert(i != &h->n); + } +#endif /* CCAN_LIST_DEBUG */ + + /* Quick test that catches a surprising number of bugs. */ + assert(!list_empty(h)); + list_del(n); +} + +/** + * list_swap - swap out an entry from an (unknown) linked list for a new one. + * @o: the list_node to replace from the list. + * @n: the list_node to insert in place of the old one. + * + * Note that this leaves @o in an undefined state; it can be added to + * another list, but not deleted/swapped again. + * + * See also: + * list_del() + * + * Example: + * struct child x1, x2; + * LIST_HEAD(xh); + * + * list_add(&xh, &x1.list); + * list_swap(&x1.list, &x2.list); + */ +#define list_swap(o, n) list_swap_(o, n, LIST_LOC) +static inline void list_swap_(struct list_node *o, + struct list_node *n, + const char* abortstr) +{ + (void)list_debug_node(o, abortstr); + *n = *o; + n->next->prev = n; + n->prev->next = n; +#ifdef CCAN_LIST_DEBUG + /* Catch use-after-del. */ + o->next = o->prev = NULL; +#endif +} + +/** + * list_entry - convert a list_node back into the structure containing it. + * @n: the list_node + * @type: the type of the entry + * @member: the list_node member of the type + * + * Example: + * // First list entry is children.next; convert back to child. + * child = list_entry(parent->children.n.next, struct child, list); + * + * See Also: + * list_top(), list_for_each() + */ +#define list_entry(n, type, member) container_of(n, type, member) + +/** + * list_top - get the first entry in a list + * @h: the list_head + * @type: the type of the entry + * @member: the list_node member of the type + * + * If the list is empty, returns NULL. + * + * Example: + * struct child *first; + * first = list_top(&parent->children, struct child, list); + * if (!first) + * printf("Empty list!\n"); + */ +#define list_top(h, type, member) \ + ((type *)list_top_((h), list_off_(type, member))) + +static inline const void *list_top_(const struct list_head *h, size_t off) +{ + if (list_empty(h)) + return NULL; + return (const char *)h->n.next - off; +} + +/** + * list_pop - remove the first entry in a list + * @h: the list_head + * @type: the type of the entry + * @member: the list_node member of the type + * + * If the list is empty, returns NULL. + * + * Example: + * struct child *one; + * one = list_pop(&parent->children, struct child, list); + * if (!one) + * printf("Empty list!\n"); + */ +#define list_pop(h, type, member) \ + ((type *)list_pop_((h), list_off_(type, member))) + +static inline const void *list_pop_(const struct list_head *h, size_t off) +{ + struct list_node *n; + + if (list_empty(h)) + return NULL; + n = h->n.next; + list_del(n); + return (const char *)n - off; +} + +/** + * list_tail - get the last entry in a list + * @h: the list_head + * @type: the type of the entry + * @member: the list_node member of the type + * + * If the list is empty, returns NULL. + * + * Example: + * struct child *last; + * last = list_tail(&parent->children, struct child, list); + * if (!last) + * printf("Empty list!\n"); + */ +#define list_tail(h, type, member) \ + ((type *)list_tail_((h), list_off_(type, member))) + +static inline const void *list_tail_(const struct list_head *h, size_t off) +{ + if (list_empty(h)) + return NULL; + return (const char *)h->n.prev - off; +} + +/** + * list_for_each - iterate through a list. + * @h: the list_head (warning: evaluated multiple times!) + * @i: the structure containing the list_node + * @member: the list_node member of the structure + * + * This is a convenient wrapper to iterate @i over the entire list. It's + * a for loop, so you can break and continue as normal. + * + * Example: + * list_for_each(&parent->children, child, list) + * printf("Name: %s\n", child->name); + */ +#define list_for_each(h, i, member) \ + list_for_each_off(h, i, list_off_var_(i, member)) + +/** + * list_for_each_rev - iterate through a list backwards. + * @h: the list_head + * @i: the structure containing the list_node + * @member: the list_node member of the structure + * + * This is a convenient wrapper to iterate @i over the entire list. It's + * a for loop, so you can break and continue as normal. + * + * Example: + * list_for_each_rev(&parent->children, child, list) + * printf("Name: %s\n", child->name); + */ +#define list_for_each_rev(h, i, member) \ + list_for_each_rev_off(h, i, list_off_var_(i, member)) + +/** + * list_for_each_rev_safe - iterate through a list backwards, + * maybe during deletion + * @h: the list_head + * @i: the structure containing the list_node + * @nxt: the structure containing the list_node + * @member: the list_node member of the structure + * + * This is a convenient wrapper to iterate @i over the entire list backwards. + * It's a for loop, so you can break and continue as normal. The extra + * variable * @nxt is used to hold the next element, so you can delete @i + * from the list. + * + * Example: + * struct child *next; + * list_for_each_rev_safe(&parent->children, child, next, list) { + * printf("Name: %s\n", child->name); + * } + */ +#define list_for_each_rev_safe(h, i, nxt, member) \ + list_for_each_rev_safe_off(h, i, nxt, list_off_var_(i, member)) + +/** + * list_for_each_safe - iterate through a list, maybe during deletion + * @h: the list_head + * @i: the structure containing the list_node + * @nxt: the structure containing the list_node + * @member: the list_node member of the structure + * + * This is a convenient wrapper to iterate @i over the entire list. It's + * a for loop, so you can break and continue as normal. The extra variable + * @nxt is used to hold the next element, so you can delete @i from the list. + * + * Example: + * list_for_each_safe(&parent->children, child, next, list) { + * list_del(&child->list); + * parent->num_children--; + * } + */ +#define list_for_each_safe(h, i, nxt, member) \ + list_for_each_safe_off(h, i, nxt, list_off_var_(i, member)) + +/** + * list_next - get the next entry in a list + * @h: the list_head + * @i: a pointer to an entry in the list. + * @member: the list_node member of the structure + * + * If @i was the last entry in the list, returns NULL. + * + * Example: + * struct child *second; + * second = list_next(&parent->children, first, list); + * if (!second) + * printf("No second child!\n"); + */ +#define list_next(h, i, member) \ + ((list_typeof(i))list_entry_or_null(list_debug(h, \ + __FILE__ ":" stringify(__LINE__)), \ + (i)->member.next, \ + list_off_var_((i), member))) + +/** + * list_prev - get the previous entry in a list + * @h: the list_head + * @i: a pointer to an entry in the list. + * @member: the list_node member of the structure + * + * If @i was the first entry in the list, returns NULL. + * + * Example: + * first = list_prev(&parent->children, second, list); + * if (!first) + * printf("Can't go back to first child?!\n"); + */ +#define list_prev(h, i, member) \ + ((list_typeof(i))list_entry_or_null(list_debug(h, \ + __FILE__ ":" stringify(__LINE__)), \ + (i)->member.prev, \ + list_off_var_((i), member))) + +/** + * list_append_list - empty one list onto the end of another. + * @to: the list to append into + * @from: the list to empty. + * + * This takes the entire contents of @from and moves it to the end of + * @to. After this @from will be empty. + * + * Example: + * struct list_head adopter; + * + * list_append_list(&adopter, &parent->children); + * assert(list_empty(&parent->children)); + * parent->num_children = 0; + */ +#define list_append_list(t, f) list_append_list_(t, f, \ + __FILE__ ":" stringify(__LINE__)) +static inline void list_append_list_(struct list_head *to, + struct list_head *from, + const char *abortstr) +{ + struct list_node *from_tail = list_debug(from, abortstr)->n.prev; + struct list_node *to_tail = list_debug(to, abortstr)->n.prev; + + /* Sew in head and entire list. */ + to->n.prev = from_tail; + from_tail->next = &to->n; + to_tail->next = &from->n; + from->n.prev = to_tail; + + /* Now remove head. */ + list_del(&from->n); + list_head_init(from); +} + +/** + * list_prepend_list - empty one list into the start of another. + * @to: the list to prepend into + * @from: the list to empty. + * + * This takes the entire contents of @from and moves it to the start + * of @to. After this @from will be empty. + * + * Example: + * list_prepend_list(&adopter, &parent->children); + * assert(list_empty(&parent->children)); + * parent->num_children = 0; + */ +#define list_prepend_list(t, f) list_prepend_list_(t, f, LIST_LOC) +static inline void list_prepend_list_(struct list_head *to, + struct list_head *from, + const char *abortstr) +{ + struct list_node *from_tail = list_debug(from, abortstr)->n.prev; + struct list_node *to_head = list_debug(to, abortstr)->n.next; + + /* Sew in head and entire list. */ + to->n.next = &from->n; + from->n.prev = &to->n; + to_head->prev = from_tail; + from_tail->next = to_head; + + /* Now remove head. */ + list_del(&from->n); + list_head_init(from); +} + +/* internal macros, do not use directly */ +#define list_for_each_off_dir_(h, i, off, dir) \ + for (i = list_node_to_off_(list_debug(h, LIST_LOC)->n.dir, \ + (off)); \ + list_node_from_off_((void *)i, (off)) != &(h)->n; \ + i = list_node_to_off_(list_node_from_off_((void *)i, (off))->dir, \ + (off))) + +#define list_for_each_safe_off_dir_(h, i, nxt, off, dir) \ + for (i = list_node_to_off_(list_debug(h, LIST_LOC)->n.dir, \ + (off)), \ + nxt = list_node_to_off_(list_node_from_off_(i, (off))->dir, \ + (off)); \ + list_node_from_off_(i, (off)) != &(h)->n; \ + i = nxt, \ + nxt = list_node_to_off_(list_node_from_off_(i, (off))->dir, \ + (off))) + +/** + * list_for_each_off - iterate through a list of memory regions. + * @h: the list_head + * @i: the pointer to a memory region wich contains list node data. + * @off: offset(relative to @i) at which list node data resides. + * + * This is a low-level wrapper to iterate @i over the entire list, used to + * implement all oher, more high-level, for-each constructs. It's a for loop, + * so you can break and continue as normal. + * + * WARNING! Being the low-level macro that it is, this wrapper doesn't know + * nor care about the type of @i. The only assumtion made is that @i points + * to a chunk of memory that at some @offset, relative to @i, contains a + * properly filled `struct node_list' which in turn contains pointers to + * memory chunks and it's turtles all the way down. Whith all that in mind + * remember that given the wrong pointer/offset couple this macro will + * happilly churn all you memory untill SEGFAULT stops it, in other words + * caveat emptor. + * + * It is worth mentioning that one of legitimate use-cases for that wrapper + * is operation on opaque types with known offset for `struct list_node' + * member(preferably 0), because it allows you not to disclose the type of + * @i. + * + * Example: + * list_for_each_off(&parent->children, child, + * offsetof(struct child, list)) + * printf("Name: %s\n", child->name); + */ +#define list_for_each_off(h, i, off) \ + list_for_each_off_dir_((h),(i),(off),next) + +/** + * list_for_each_rev_off - iterate through a list of memory regions backwards + * @h: the list_head + * @i: the pointer to a memory region wich contains list node data. + * @off: offset(relative to @i) at which list node data resides. + * + * See list_for_each_off for details + */ +#define list_for_each_rev_off(h, i, off) \ + list_for_each_off_dir_((h),(i),(off),prev) + +/** + * list_for_each_safe_off - iterate through a list of memory regions, maybe + * during deletion + * @h: the list_head + * @i: the pointer to a memory region wich contains list node data. + * @nxt: the structure containing the list_node + * @off: offset(relative to @i) at which list node data resides. + * + * For details see `list_for_each_off' and `list_for_each_safe' + * descriptions. + * + * Example: + * list_for_each_safe_off(&parent->children, child, + * next, offsetof(struct child, list)) + * printf("Name: %s\n", child->name); + */ +#define list_for_each_safe_off(h, i, nxt, off) \ + list_for_each_safe_off_dir_((h),(i),(nxt),(off),next) + +/** + * list_for_each_rev_safe_off - iterate backwards through a list of + * memory regions, maybe during deletion + * @h: the list_head + * @i: the pointer to a memory region wich contains list node data. + * @nxt: the structure containing the list_node + * @off: offset(relative to @i) at which list node data resides. + * + * For details see `list_for_each_rev_off' and `list_for_each_rev_safe' + * descriptions. + * + * Example: + * list_for_each_rev_safe_off(&parent->children, child, + * next, offsetof(struct child, list)) + * printf("Name: %s\n", child->name); + */ +#define list_for_each_rev_safe_off(h, i, nxt, off) \ + list_for_each_safe_off_dir_((h),(i),(nxt),(off),prev) + +/* Other -off variants. */ +#define list_entry_off(n, type, off) \ + ((type *)list_node_from_off_((n), (off))) + +#define list_head_off(h, type, off) \ + ((type *)list_head_off((h), (off))) + +#define list_tail_off(h, type, off) \ + ((type *)list_tail_((h), (off))) + +#define list_add_off(h, n, off) \ + list_add((h), list_node_from_off_((n), (off))) + +#define list_del_off(n, off) \ + list_del(list_node_from_off_((n), (off))) + +#define list_del_from_off(h, n, off) \ + list_del_from(h, list_node_from_off_((n), (off))) + +/* Offset helper functions so we only single-evaluate. */ +static inline void *list_node_to_off_(struct list_node *node, size_t off) +{ + return (void *)((char *)node - off); +} +static inline struct list_node *list_node_from_off_(void *ptr, size_t off) +{ + return (struct list_node *)((char *)ptr + off); +} + +/* Get the offset of the member, but make sure it's a list_node. */ +#define list_off_(type, member) \ + (container_off(type, member) + \ + check_type(((type *)0)->member, struct list_node)) + +#define list_off_var_(var, member) \ + (container_off_var(var, member) + \ + check_type(var->member, struct list_node)) + +#if HAVE_TYPEOF +#define list_typeof(var) typeof(var) +#else +#define list_typeof(var) void * +#endif + +/* Returns member, or NULL if at end of list. */ +static inline void *list_entry_or_null(const struct list_head *h, + const struct list_node *n, + size_t off) +{ + if (n == &h->n) + return NULL; + return (char *)n - off; +} +#endif /* CCAN_LIST_H */ diff --git a/ccan/minmax.h b/ccan/minmax.h new file mode 100644 index 000000000..5642f6523 --- /dev/null +++ b/ccan/minmax.h @@ -0,0 +1,65 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#ifndef CCAN_MINMAX_H +#define CCAN_MINMAX_H + +#include "config.h" + +#include + +#if !HAVE_STATEMENT_EXPR || !HAVE_TYPEOF +/* + * Without these, there's no way to avoid unsafe double evaluation of + * the arguments + */ +#error Sorry, minmax module requires statement expressions and typeof +#endif + +#if HAVE_BUILTIN_TYPES_COMPATIBLE_P +#define MINMAX_ASSERT_COMPATIBLE(a, b) \ + BUILD_ASSERT(__builtin_types_compatible_p(a, b)) +#else +#define MINMAX_ASSERT_COMPATIBLE(a, b) \ + do { } while (0) +#endif + +#define min(a, b) \ + ({ \ + typeof(a) _a = (a); \ + typeof(b) _b = (b); \ + MINMAX_ASSERT_COMPATIBLE(typeof(_a), typeof(_b)); \ + _a < _b ? _a : _b; \ + }) + +#define max(a, b) \ + ({ \ + typeof(a) _a = (a); \ + typeof(b) _b = (b); \ + MINMAX_ASSERT_COMPATIBLE(typeof(_a), typeof(_b)); \ + _a > _b ? _a : _b; \ + }) + +#define clamp(v, f, c) (max(min((v), (c)), (f))) + + +#define min_t(t, a, b) \ + ({ \ + t _ta = (a); \ + t _tb = (b); \ + min(_ta, _tb); \ + }) +#define max_t(t, a, b) \ + ({ \ + t _ta = (a); \ + t _tb = (b); \ + max(_ta, _tb); \ + }) + +#define clamp_t(t, v, f, c) \ + ({ \ + t _tv = (v); \ + t _tf = (f); \ + t _tc = (c); \ + clamp(_tv, _tf, _tc); \ + }) + +#endif /* CCAN_MINMAX_H */ diff --git a/ccan/str.c b/ccan/str.c new file mode 100644 index 000000000..e1daadbfd --- /dev/null +++ b/ccan/str.c @@ -0,0 +1,13 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#include + +size_t strcount(const char *haystack, const char *needle) +{ + size_t i = 0, nlen = strlen(needle); + + while ((haystack = strstr(haystack, needle)) != NULL) { + i++; + haystack += nlen; + } + return i; +} diff --git a/ccan/str.h b/ccan/str.h new file mode 100644 index 000000000..4e268b3ae --- /dev/null +++ b/ccan/str.h @@ -0,0 +1,228 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#ifndef CCAN_STR_H +#define CCAN_STR_H +#include "config.h" +#include +#include +#include +#include + +/** + * streq - Are two strings equal? + * @a: first string + * @b: first string + * + * This macro is arguably more readable than "!strcmp(a, b)". + * + * Example: + * if (streq(somestring, "")) + * printf("String is empty!\n"); + */ +#define streq(a,b) (strcmp((a),(b)) == 0) + +/** + * strstarts - Does this string start with this prefix? + * @str: string to test + * @prefix: prefix to look for at start of str + * + * Example: + * if (strstarts(somestring, "foo")) + * printf("String %s begins with 'foo'!\n", somestring); + */ +#define strstarts(str,prefix) (strncmp((str),(prefix),strlen(prefix)) == 0) + +/** + * strends - Does this string end with this postfix? + * @str: string to test + * @postfix: postfix to look for at end of str + * + * Example: + * if (strends(somestring, "foo")) + * printf("String %s end with 'foo'!\n", somestring); + */ +static inline bool strends(const char *str, const char *postfix) +{ + if (strlen(str) < strlen(postfix)) + return false; + + return streq(str + strlen(str) - strlen(postfix), postfix); +} + +/** + * stringify - Turn expression into a string literal + * @expr: any C expression + * + * Example: + * #define PRINT_COND_IF_FALSE(cond) \ + * ((cond) || printf("%s is false!", stringify(cond))) + */ +#define stringify(expr) stringify_1(expr) +/* Double-indirection required to stringify expansions */ +#define stringify_1(expr) #expr + +/** + * strcount - Count number of (non-overlapping) occurrences of a substring. + * @haystack: a C string + * @needle: a substring + * + * Example: + * assert(strcount("aaa aaa", "a") == 6); + * assert(strcount("aaa aaa", "ab") == 0); + * assert(strcount("aaa aaa", "aa") == 2); + */ +size_t strcount(const char *haystack, const char *needle); + +/** + * STR_MAX_CHARS - Maximum possible size of numeric string for this type. + * @type_or_expr: a pointer or integer type or expression. + * + * This provides enough space for a nul-terminated string which represents the + * largest possible value for the type or expression. + * + * Note: The implementation adds extra space so hex values or negative + * values will fit (eg. sprintf(... "%p"). ) + * + * Example: + * char str[STR_MAX_CHARS(int)]; + * + * sprintf(str, "%i", 7); + */ +#define STR_MAX_CHARS(type_or_expr) \ + ((sizeof(type_or_expr) * CHAR_BIT + 8) / 9 * 3 + 2 \ + + STR_MAX_CHARS_TCHECK_(type_or_expr)) + +#if HAVE_TYPEOF +/* Only a simple type can have 0 assigned, so test that. */ +#define STR_MAX_CHARS_TCHECK_(type_or_expr) \ + ({ typeof(type_or_expr) x = 0; (void)x; 0; }) +#else +#define STR_MAX_CHARS_TCHECK_(type_or_expr) 0 +#endif + +/** + * cisalnum - isalnum() which takes a char (and doesn't accept EOF) + * @c: a character + * + * Surprisingly, the standard ctype.h isalnum() takes an int, which + * must have the value of EOF (-1) or an unsigned char. This variant + * takes a real char, and doesn't accept EOF. + */ +static inline bool cisalnum(char c) +{ + return isalnum((unsigned char)c); +} +static inline bool cisalpha(char c) +{ + return isalpha((unsigned char)c); +} +static inline bool cisascii(char c) +{ + return isascii((unsigned char)c); +} +#if HAVE_ISBLANK +static inline bool cisblank(char c) +{ + return isblank((unsigned char)c); +} +#endif +static inline bool ciscntrl(char c) +{ + return iscntrl((unsigned char)c); +} +static inline bool cisdigit(char c) +{ + return isdigit((unsigned char)c); +} +static inline bool cisgraph(char c) +{ + return isgraph((unsigned char)c); +} +static inline bool cislower(char c) +{ + return islower((unsigned char)c); +} +static inline bool cisprint(char c) +{ + return isprint((unsigned char)c); +} +static inline bool cispunct(char c) +{ + return ispunct((unsigned char)c); +} +static inline bool cisspace(char c) +{ + return isspace((unsigned char)c); +} +static inline bool cisupper(char c) +{ + return isupper((unsigned char)c); +} +static inline bool cisxdigit(char c) +{ + return isxdigit((unsigned char)c); +} + +#include + +/* These checks force things out of line, hence they are under DEBUG. */ +#ifdef CCAN_STR_DEBUG +#include + +/* These are commonly misused: they take -1 or an *unsigned* char value. */ +#undef isalnum +#undef isalpha +#undef isascii +#undef isblank +#undef iscntrl +#undef isdigit +#undef isgraph +#undef islower +#undef isprint +#undef ispunct +#undef isspace +#undef isupper +#undef isxdigit + +/* You can use a char if char is unsigned. */ +#if HAVE_BUILTIN_TYPES_COMPATIBLE_P && HAVE_TYPEOF +#define str_check_arg_(i) \ + ((i) + BUILD_ASSERT_OR_ZERO(!__builtin_types_compatible_p(typeof(i), \ + char) \ + || (char)255 > 0)) +#else +#define str_check_arg_(i) (i) +#endif + +#define isalnum(i) str_isalnum(str_check_arg_(i)) +#define isalpha(i) str_isalpha(str_check_arg_(i)) +#define isascii(i) str_isascii(str_check_arg_(i)) +#if HAVE_ISBLANK +#define isblank(i) str_isblank(str_check_arg_(i)) +#endif +#define iscntrl(i) str_iscntrl(str_check_arg_(i)) +#define isdigit(i) str_isdigit(str_check_arg_(i)) +#define isgraph(i) str_isgraph(str_check_arg_(i)) +#define islower(i) str_islower(str_check_arg_(i)) +#define isprint(i) str_isprint(str_check_arg_(i)) +#define ispunct(i) str_ispunct(str_check_arg_(i)) +#define isspace(i) str_isspace(str_check_arg_(i)) +#define isupper(i) str_isupper(str_check_arg_(i)) +#define isxdigit(i) str_isxdigit(str_check_arg_(i)) + +#if HAVE_TYPEOF +/* With GNU magic, we can make const-respecting standard string functions. */ +#undef strstr +#undef strchr +#undef strrchr + +/* + 0 is needed to decay array into pointer. */ +#define strstr(haystack, needle) \ + ((typeof((haystack) + 0))str_strstr((haystack), (needle))) +#define strchr(haystack, c) \ + ((typeof((haystack) + 0))str_strchr((haystack), (c))) +#define strrchr(haystack, c) \ + ((typeof((haystack) + 0))str_strrchr((haystack), (c))) +#endif +#endif /* CCAN_STR_DEBUG */ + +#endif /* CCAN_STR_H */ diff --git a/ccan/str_debug.h b/ccan/str_debug.h new file mode 100644 index 000000000..92c10c41c --- /dev/null +++ b/ccan/str_debug.h @@ -0,0 +1,30 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#ifndef CCAN_STR_DEBUG_H +#define CCAN_STR_DEBUG_H + +/* #define CCAN_STR_DEBUG 1 */ + +#ifdef CCAN_STR_DEBUG +/* Because we mug the real ones with macros, we need our own wrappers. */ +int str_isalnum(int i); +int str_isalpha(int i); +int str_isascii(int i); +#if HAVE_ISBLANK +int str_isblank(int i); +#endif +int str_iscntrl(int i); +int str_isdigit(int i); +int str_isgraph(int i); +int str_islower(int i); +int str_isprint(int i); +int str_ispunct(int i); +int str_isspace(int i); +int str_isupper(int i); +int str_isxdigit(int i); + +char *str_strstr(const char *haystack, const char *needle); +char *str_strchr(const char *s, int c); +char *str_strrchr(const char *s, int c); +#endif /* CCAN_STR_DEBUG */ + +#endif /* CCAN_STR_DEBUG_H */ diff --git a/ibacm/CMakeLists.txt b/ibacm/CMakeLists.txt index 8887c13af..3a8ac3290 100644 --- a/ibacm/CMakeLists.txt +++ b/ibacm/CMakeLists.txt @@ -18,7 +18,7 @@ rdma_sbin_executable(ibacm src/acm.c src/acm_util.c ) -target_link_libraries(ibacm +target_link_libraries(ibacm LINK_PRIVATE ibverbs ibumad ${CMAKE_THREAD_LIBS_INIT} @@ -32,7 +32,7 @@ add_library(ibacmp MODULE prov/acmp/src/acmp.c ) rdma_set_library_map(ibacmp "prov/acmp/src/libibacmp.map") -target_link_libraries(ibacmp +target_link_libraries(ibacmp LINK_PRIVATE ibacm ibverbs ibumad @@ -48,7 +48,7 @@ rdma_executable(ib_acme src/libacm.c src/parse.c ) -target_link_libraries(ib_acme +target_link_libraries(ib_acme LINK_PRIVATE ibverbs ) target_compile_definitions(ib_acme PRIVATE "-DACME_PRINTS") diff --git a/ibacm/linux/osd.h b/ibacm/linux/osd.h index 5ca4c6f55..f03980faf 100644 --- a/ibacm/linux/osd.h +++ b/ibacm/linux/osd.h @@ -46,6 +46,8 @@ #include #include +#include + #define ACM_CONF_DIR IBACM_CONFIG_PATH #define ACM_ADDR_FILE "ibacm_addr.cfg" #define ACM_OPTS_FILE "ibacm_opts.cfg" @@ -53,12 +55,6 @@ #define LIB_DESTRUCTOR __attribute__((destructor)) #define CDECL_FUNC -#define container_of(ptr, type, field) \ - ((type *) ((void *) ptr - offsetof(type, field))) - -#define min(a, b) (a < b ? a : b) -#define max(a, b) (a > b ? a : b) - #if __BYTE_ORDER == __LITTLE_ENDIAN #define htonll(x) bswap_64(x) #else diff --git a/ibacm/prov/acmp/src/acmp.c b/ibacm/prov/acmp/src/acmp.c index a26ed8369..75231bfef 100644 --- a/ibacm/prov/acmp/src/acmp.c +++ b/ibacm/prov/acmp/src/acmp.c @@ -629,7 +629,7 @@ static int acmp_best_mc_index(struct acmp_ep *ep, struct acm_resolve_rec *rec) { int i, index; - for (i = min(rec->gid_cnt, ACM_MAX_GID_COUNT) - 1; i >= 0; i--) { + for (i = min_t(int, rec->gid_cnt, ACM_MAX_GID_COUNT) - 1; i >= 0; i--) { index = acmp_mc_index(ep, &rec->gid[i]); if (index >= 0) { return index; diff --git a/iwpmd/src/CMakeLists.txt b/iwpmd/src/CMakeLists.txt index e6255b597..727db7eff 100644 --- a/iwpmd/src/CMakeLists.txt +++ b/iwpmd/src/CMakeLists.txt @@ -3,7 +3,7 @@ rdma_executable(iwpmd iwarp_pm_helper.c iwarp_pm_server.c ) -target_link_libraries(iwpmd +target_link_libraries(iwpmd LINK_PRIVATE ${NL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ) diff --git a/libibcm/examples/CMakeLists.txt b/libibcm/examples/CMakeLists.txt index a90639dae..ef30a6e17 100644 --- a/libibcm/examples/CMakeLists.txt +++ b/libibcm/examples/CMakeLists.txt @@ -1,2 +1,2 @@ rdma_test_executable(cmpost cmpost.c) -target_link_libraries(cmpost ibcm rdmacm) +target_link_libraries(cmpost LINK_PRIVATE ibcm rdmacm) diff --git a/libibcm/src/cm.c b/libibcm/src/cm.c index 5c56381fd..f5318f01f 100644 --- a/libibcm/src/cm.c +++ b/libibcm/src/cm.c @@ -121,11 +121,6 @@ struct cm_id_private { pthread_mutex_t mut; }; -#ifndef container_of -#define container_of(ptr, type, field) \ - ((type *) ((void *)ptr - offsetof(type, field))) -#endif - static int check_abi_version(void) { char value[8]; diff --git a/libibumad/tests/CMakeLists.txt b/libibumad/tests/CMakeLists.txt index 9676029c8..7508e0807 100644 --- a/libibumad/tests/CMakeLists.txt +++ b/libibumad/tests/CMakeLists.txt @@ -1,5 +1,5 @@ rdma_test_executable(umad_reg2 umad_reg2_compat.c) -target_link_libraries(umad_reg2 ibumad) +target_link_libraries(umad_reg2 LINK_PRIVATE ibumad) rdma_test_executable(umad_register2 umad_register2.c) -target_link_libraries(umad_register2 ibumad) +target_link_libraries(umad_register2 LINK_PRIVATE ibumad) diff --git a/libibverbs/examples/CMakeLists.txt b/libibverbs/examples/CMakeLists.txt index 5fc47ba11..76e333bd0 100644 --- a/libibverbs/examples/CMakeLists.txt +++ b/libibverbs/examples/CMakeLists.txt @@ -6,25 +6,25 @@ add_library(ibverbs_tools STATIC ) rdma_executable(ibv_asyncwatch asyncwatch.c) -target_link_libraries(ibv_asyncwatch ibverbs) +target_link_libraries(ibv_asyncwatch LINK_PRIVATE ibverbs) rdma_executable(ibv_devices device_list.c) -target_link_libraries(ibv_devices ibverbs) +target_link_libraries(ibv_devices LINK_PRIVATE ibverbs) rdma_executable(ibv_devinfo devinfo.c) -target_link_libraries(ibv_devinfo ibverbs) +target_link_libraries(ibv_devinfo LINK_PRIVATE ibverbs) rdma_executable(ibv_rc_pingpong rc_pingpong.c) -target_link_libraries(ibv_rc_pingpong ibverbs ibverbs_tools) +target_link_libraries(ibv_rc_pingpong LINK_PRIVATE ibverbs ibverbs_tools) rdma_executable(ibv_srq_pingpong srq_pingpong.c) -target_link_libraries(ibv_srq_pingpong ibverbs ibverbs_tools) +target_link_libraries(ibv_srq_pingpong LINK_PRIVATE ibverbs ibverbs_tools) rdma_executable(ibv_uc_pingpong uc_pingpong.c) -target_link_libraries(ibv_uc_pingpong ibverbs ibverbs_tools) +target_link_libraries(ibv_uc_pingpong LINK_PRIVATE ibverbs ibverbs_tools) rdma_executable(ibv_ud_pingpong ud_pingpong.c) -target_link_libraries(ibv_ud_pingpong ibverbs ibverbs_tools) +target_link_libraries(ibv_ud_pingpong LINK_PRIVATE ibverbs ibverbs_tools) rdma_executable(ibv_xsrq_pingpong xsrq_pingpong.c) -target_link_libraries(ibv_xsrq_pingpong ibverbs ibverbs_tools) +target_link_libraries(ibv_xsrq_pingpong LINK_PRIVATE ibverbs ibverbs_tools) diff --git a/libibverbs/examples/rc_pingpong.c b/libibverbs/examples/rc_pingpong.c index 967678362..3bbf23d11 100644 --- a/libibverbs/examples/rc_pingpong.c +++ b/libibverbs/examples/rc_pingpong.c @@ -49,13 +49,7 @@ #include "pingpong.h" -#ifndef max -#define max(x, y) (((x) > (y)) ? (x) : (y)) -#endif - -#ifndef min -#define min(x, y) (((x) < (y)) ? (x) : (y)) -#endif +#include enum { PINGPONG_RECV_WRID = 1, @@ -586,8 +580,8 @@ static int pp_post_send(struct pingpong_context *ctx) } struct ts_params { - unsigned int comp_recv_max_time_delta; - unsigned int comp_recv_min_time_delta; + uint64_t comp_recv_max_time_delta; + uint64_t comp_recv_min_time_delta; uint64_t comp_recv_total_time_delta; uint64_t comp_recv_prev_time; int last_comp_with_ts; diff --git a/libmlx5/src/buf.c b/libmlx5/src/buf.c index c827930fd..1a681c6a3 100644 --- a/libmlx5/src/buf.c +++ b/libmlx5/src/buf.c @@ -259,7 +259,6 @@ static int alloc_huge_buf(struct mlx5_context *mctx, struct mlx5_buf *buf, size_t size, int page_size) { int found = 0; - LIST_HEAD(slist); int nchunk; struct mlx5_hugetlb_mem *hmem; int ret; @@ -268,7 +267,7 @@ static int alloc_huge_buf(struct mlx5_context *mctx, struct mlx5_buf *buf, nchunk = buf->length / MLX5_Q_CHUNK_SIZE; mlx5_spin_lock(&mctx->hugetlb_lock); - list_for_each_entry(hmem, &mctx->hugetlb_list, list) { + list_for_each(&mctx->hugetlb_list, hmem, entry) { if (bitmap_avail(&hmem->bitmap)) { buf->base = bitmap_alloc_range(&hmem->bitmap, nchunk, 1); if (buf->base != -1) { @@ -297,9 +296,9 @@ static int alloc_huge_buf(struct mlx5_context *mctx, struct mlx5_buf *buf, mlx5_spin_lock(&mctx->hugetlb_lock); if (bitmap_avail(&hmem->bitmap)) - list_add(&hmem->list, &mctx->hugetlb_list); + list_add(&mctx->hugetlb_list, &hmem->entry); else - list_add_tail(&hmem->list, &mctx->hugetlb_list); + list_add_tail(&mctx->hugetlb_list, &hmem->entry); mlx5_spin_unlock(&mctx->hugetlb_lock); } @@ -318,7 +317,7 @@ static int alloc_huge_buf(struct mlx5_context *mctx, struct mlx5_buf *buf, mlx5_spin_lock(&mctx->hugetlb_lock); bitmap_free_range(&hmem->bitmap, buf->base, nchunk); if (bitmap_empty(&hmem->bitmap)) { - list_del(&hmem->list); + list_del(&hmem->entry); mlx5_spin_unlock(&mctx->hugetlb_lock); free_huge_mem(hmem); } else @@ -335,7 +334,7 @@ static void free_huge_buf(struct mlx5_context *ctx, struct mlx5_buf *buf) mlx5_spin_lock(&ctx->hugetlb_lock); bitmap_free_range(&buf->hmem->bitmap, buf->base, nchunk); if (bitmap_empty(&buf->hmem->bitmap)) { - list_del(&buf->hmem->list); + list_del(&buf->hmem->entry); mlx5_spin_unlock(&ctx->hugetlb_lock); free_huge_mem(buf->hmem); } else diff --git a/libmlx5/src/list.h b/libmlx5/src/list.h deleted file mode 100644 index cd7d25ba3..000000000 --- a/libmlx5/src/list.h +++ /dev/null @@ -1,331 +0,0 @@ -#ifndef _LINUX_LIST_H -#define _LINUX_LIST_H - -/* - * These are non-NULL pointers that will result in page faults - * under normal circumstances, used to verify that nobody uses - * non-initialized list entries. - */ -#define LIST_POISON1 ((void *) 0x00100100) -#define LIST_POISON2 ((void *) 0x00200200) - -/* - * Simple doubly linked list implementation. - * - * Some of the internal functions ("__xxx") are useful when - * manipulating whole lists rather than single entries, as - * sometimes we already know the next/prev entries and we can - * generate better code by using them directly rather than - * using the generic single-entry routines. - */ - -struct list_head { - struct list_head *next, *prev; -}; - -#define LIST_HEAD_INIT(name) { &(name), &(name) } - -#define LIST_HEAD(name) \ - struct list_head name = LIST_HEAD_INIT(name) - -#define INIT_LIST_HEAD(ptr) do { \ - (ptr)->next = (ptr); (ptr)->prev = (ptr); \ -} while (0) - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_add(struct list_head *new, - struct list_head *prev, - struct list_head *next) -{ - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - -/** - * list_add - add a new entry - * @new: new entry to be added - * @head: list head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - */ -static inline void list_add(struct list_head *new, struct list_head *head) -{ - __list_add(new, head, head->next); -} - -/** - * list_add_tail - add a new entry - * @new: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - */ -static inline void list_add_tail(struct list_head *new, struct list_head *head) -{ - __list_add(new, head->prev, head); -} - -/* - * Delete a list entry by making the prev/next entries - * point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_del(struct list_head *prev, struct list_head *next) -{ - next->prev = prev; - prev->next = next; -} - -/** - * list_del - deletes entry from list. - * @entry: the element to delete from the list. - * Note: list_empty on entry does not return true after this, the entry is - * in an undefined state. - */ -static inline void list_del(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - entry->next = LIST_POISON1; - entry->prev = LIST_POISON2; -} - -/** - * list_del_init - deletes entry from list and reinitialize it. - * @entry: the element to delete from the list. - */ -static inline void list_del_init(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - INIT_LIST_HEAD(entry); -} - -/** - * list_move - delete from one list and add as another's head - * @list: the entry to move - * @head: the head that will precede our entry - */ -static inline void list_move(struct list_head *list, struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add(list, head); -} - -/** - * list_move_tail - delete from one list and add as another's tail - * @list: the entry to move - * @head: the head that will follow our entry - */ -static inline void list_move_tail(struct list_head *list, - struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add_tail(list, head); -} - -/** - * list_empty - tests whether a list is empty - * @head: the list to test. - */ -static inline int list_empty(const struct list_head *head) -{ - return head->next == head; -} - -/** - * list_empty_careful - tests whether a list is - * empty _and_ checks that no other CPU might be - * in the process of still modifying either member - * - * NOTE: using list_empty_careful() without synchronization - * can only be safe if the only activity that can happen - * to the list entry is list_del_init(). Eg. it cannot be used - * if another CPU could re-list_add() it. - * - * @head: the list to test. - */ -static inline int list_empty_careful(const struct list_head *head) -{ - struct list_head *next = head->next; - return (next == head) && (next == head->prev); -} - -static inline void __list_splice(struct list_head *list, - struct list_head *head) -{ - struct list_head *first = list->next; - struct list_head *last = list->prev; - struct list_head *at = head->next; - - first->prev = head; - head->next = first; - - last->next = at; - at->prev = last; -} - -/** - * list_splice - join two lists - * @list: the new list to add. - * @head: the place to add it in the first list. - */ -static inline void list_splice(struct list_head *list, struct list_head *head) -{ - if (!list_empty(list)) - __list_splice(list, head); -} - -/** - * list_splice_init - join two lists and reinitialise the emptied list. - * @list: the new list to add. - * @head: the place to add it in the first list. - * - * The list at @list is reinitialised - */ -static inline void list_splice_init(struct list_head *list, - struct list_head *head) -{ - if (!list_empty(list)) { - __list_splice(list, head); - INIT_LIST_HEAD(list); - } -} - -#ifndef offsetof -#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) -#endif - -/** - * container_of - cast a member of a structure out to the containing structure - * - * @ptr: the pointer to the member. - * @type: the type of the container struct this is embedded in. - * @member: the name of the member within the struct. - * - */ -#ifndef container_of -#define container_of(ptr, type, member) ({ \ - const typeof(((type *)0)->member)*__mptr = (ptr); \ - (type *)((char *)__mptr - offsetof(type, member)); }) -#endif - - -/** - * list_entry - get the struct for this entry - * @ptr: the &struct list_head pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - */ -#define list_entry(ptr, type, member) \ - container_of(ptr, type, member) - -/** - * list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each(pos, head) \ - for (pos = (head)->next; prefetch(pos->next), pos != (head); \ - pos->next) - -/** - * __list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - * - * This variant differs from list_for_each() in that it's the - * simplest possible list iteration code, no prefetching is done. - * Use this for code that knows the list to be very short (empty - * or 1 entry) most of the time. - */ -#define __list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); pos = pos->next) - -/** - * list_for_each_prev - iterate over a list backwards - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each_prev(pos, head) \ - for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \ - pos = pos->prev) - -/** - * list_for_each_safe - iterate over a list safe against removal of list entry - * @pos: the &struct list_head to use as a loop counter. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. - */ -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) - -/** - * list_for_each_entry - iterate over list of given type - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry(pos, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member)) - -/** - * list_for_each_entry_reverse - iterate backwards over list of given type. - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_reverse(pos, head, member) \ - for (pos = list_entry((head)->prev, typeof(*pos), member); \ - prefetch(pos->member.prev), &pos->member != (head); \ - pos = list_entry(pos->member.prev, typeof(*pos), member)) - -/** - * list_prepare_entry - prepare a pos entry for use as a start point in - * list_for_each_entry_continue - * @pos: the type * to use as a start point - * @head: the head of the list - * @member: the name of the list_struct within the struct. - */ -#define list_prepare_entry(pos, head, member) \ - ((pos) ? : list_entry(head, typeof(*pos), member)) - -/** - * list_for_each_entry_continue - iterate over list of given type - * continuing after existing point - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_continue(pos, head, member) \ - for (pos = list_entry(pos->member.next, typeof(*pos), member); \ - prefetch(pos->member.next), &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member)) - -/** - * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry - * @pos: the type * to use as a loop counter. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_safe(pos, n, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member), \ - n = list_entry(pos->member.next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, typeof(*n), member)) - -#endif - diff --git a/libmlx5/src/mlx5.c b/libmlx5/src/mlx5.c index 262a9691e..058b52fcd 100644 --- a/libmlx5/src/mlx5.c +++ b/libmlx5/src/mlx5.c @@ -730,7 +730,7 @@ static int mlx5_init_context(struct verbs_device *vdev, mlx5_read_env(&vdev->device, context); mlx5_spinlock_init(&context->hugetlb_lock); - INIT_LIST_HEAD(&context->hugetlb_list); + list_head_init(&context->hugetlb_list); context->ibv_ctx.ops = mlx5_ctx_ops; diff --git a/libmlx5/src/mlx5.h b/libmlx5/src/mlx5.h index dc90892d8..6c4e83002 100644 --- a/libmlx5/src/mlx5.h +++ b/libmlx5/src/mlx5.h @@ -39,8 +39,9 @@ #include #include #include "mlx5-abi.h" -#include "list.h" +#include #include "bitmap.h" +#include #ifdef __GNUC__ #define likely(x) __builtin_expect((x), 1) @@ -91,20 +92,6 @@ #endif -#ifndef min -#define min(a, b) \ - ({ typeof(a) _a = (a); \ - typeof(b) _b = (b); \ - _a < _b ? _a : _b; }) -#endif - -#ifndef max -#define max(a, b) \ - ({ typeof(a) _a = (a); \ - typeof(b) _b = (b); \ - _a > _b ? _a : _b; }) -#endif - #define HIDDEN __attribute__((visibility("hidden"))) #ifdef HAVE_FUNC_ATTRIBUTE_ALWAYS_INLINE @@ -367,7 +354,7 @@ struct mlx5_hugetlb_mem { int shmid; void *shmaddr; struct mlx5_bitmap bitmap; - struct list_head list; + struct list_node entry; }; struct mlx5_buf { diff --git a/libmlx5/src/qp.c b/libmlx5/src/qp.c index 1e1164cea..9363fddc3 100644 --- a/libmlx5/src/qp.c +++ b/libmlx5/src/qp.c @@ -82,7 +82,7 @@ static int copy_to_scat(struct mlx5_wqe_data_seg *scat, void *buf, int *size, return IBV_WC_SUCCESS; for (i = 0; i < max; ++i) { - copy = min(*size, ntohl(scat->byte_count)); + copy = min_t(long, *size, ntohl(scat->byte_count)); memcpy((void *)(unsigned long)ntohll(scat->addr), buf, copy); *size -= copy; if (*size == 0) @@ -364,7 +364,7 @@ static inline int copy_eth_inline_headers(struct ibv_qp *ibqp, struct mlx5_wqe_eth_seg *eseg, struct mlx5_sg_copy_ptr *sg_copy_ptr) { - int inl_hdr_size = MLX5_ETH_L2_INLINE_HEADER_SIZE; + uint32_t inl_hdr_size = MLX5_ETH_L2_INLINE_HEADER_SIZE; int inl_hdr_copy_size = 0; int j = 0; FILE *fp = to_mctx(ibqp->context)->dbg_fp; diff --git a/libmlx5/src/srq.c b/libmlx5/src/srq.c index dbf53df2d..24979bfb6 100644 --- a/libmlx5/src/srq.c +++ b/libmlx5/src/srq.c @@ -61,7 +61,7 @@ int mlx5_copy_to_recv_srq(struct mlx5_srq *srq, int idx, void *buf, int size) scat = (struct mlx5_wqe_data_seg *) (next + 1); for (i = 0; i < max; ++i) { - copy = min(size, ntohl(scat->byte_count)); + copy = min_t(long, size, ntohl(scat->byte_count)); memcpy((void *)(unsigned long)ntohll(scat->addr), buf, copy); size -= copy; if (size <= 0) diff --git a/libmlx5/src/verbs.c b/libmlx5/src/verbs.c index 52289acc3..e7f4e3147 100644 --- a/libmlx5/src/verbs.c +++ b/libmlx5/src/verbs.c @@ -728,10 +728,11 @@ int mlx5_destroy_srq(struct ibv_srq *srq) static int sq_overhead(enum ibv_qp_type qp_type) { - int size = 0; - size_t mw_bind_size = sizeof(struct mlx5_wqe_umr_ctrl_seg) + - sizeof(struct mlx5_wqe_mkey_context_seg) + - max(sizeof(struct mlx5_wqe_umr_klm_seg), 64); + size_t size = 0; + size_t mw_bind_size = + sizeof(struct mlx5_wqe_umr_ctrl_seg) + + sizeof(struct mlx5_wqe_mkey_context_seg) + + max_t(size_t, sizeof(struct mlx5_wqe_umr_klm_seg), 64); switch (qp_type) { case IBV_QPT_RC: @@ -813,18 +814,18 @@ static int mlx5_calc_rcv_wqe(struct mlx5_context *ctx, struct ibv_qp_init_attr_ex *attr, struct mlx5_qp *qp) { - int size; + uint32_t size; int num_scatter; if (attr->srq) return 0; - num_scatter = max(attr->cap.max_recv_sge, 1); + num_scatter = max_t(uint32_t, attr->cap.max_recv_sge, 1); size = sizeof(struct mlx5_wqe_data_seg) * num_scatter; if (qp->wq_sig) size += sizeof(struct mlx5_rwqe_sig); - if (size < 0 || size > ctx->max_rq_desc_sz) + if (size > ctx->max_rq_desc_sz) return -EINVAL; size = mlx5_round_up_power_of_two(size); @@ -885,16 +886,16 @@ static int mlx5_calc_rwq_size(struct mlx5_context *ctx, struct mlx5_rwq *rwq, struct ibv_wq_init_attr *attr) { - int wqe_size; + size_t wqe_size; int wq_size; - int num_scatter; + uint32_t num_scatter; int scat_spc; if (!attr->max_wr) return -EINVAL; /* TBD: check caps for RQ */ - num_scatter = max(attr->max_sge, 1); + num_scatter = max_t(uint32_t, attr->max_sge, 1); wqe_size = sizeof(struct mlx5_wqe_data_seg) * num_scatter; if (rwq->wq_sig) diff --git a/libocrdma/src/ocrdma_list.h b/libocrdma/src/ocrdma_list.h deleted file mode 100644 index 1e0f1ff6d..000000000 --- a/libocrdma/src/ocrdma_list.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2008-2013 Emulex. All rights reserved. - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __OCRDMA_LIST_H__ -#define __OCRDMA_LIST_H__ - -struct ocrdma_list_node { - struct ocrdma_list_node *next, *prev; -}; - -struct ocrdma_list_head { - struct ocrdma_list_node node; - pthread_mutex_t lock; -}; - -#define DBLY_LIST_HEAD_INIT(name) { { &(name.node), &(name.node) } , \ - PTHREAD_MUTEX_INITIALIZER } - -#define DBLY_LIST_HEAD(name) \ - struct ocrdma_list_head name = DBLY_LIST_HEAD_INIT(name); \ - -#define INIT_DBLY_LIST_NODE(ptr) do { \ - (ptr)->next = (ptr); (ptr)->prev = (ptr); \ -} while (0) - -#define INIT_DBLY_LIST_HEAD(ptr) INIT_DBLY_LIST_NODE(ptr.node) - -static inline void __list_add_node(struct ocrdma_list_node *new, - struct ocrdma_list_node *prev, - struct ocrdma_list_node *next) -{ - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - -static inline void list_add_node_tail(struct ocrdma_list_node *new, - struct ocrdma_list_head *head) -{ - __list_add_node(new, head->node.prev, &head->node); -} - -static inline void __list_del_node(struct ocrdma_list_node *prev, - struct ocrdma_list_node *next) -{ - next->prev = prev; - prev->next = next; -} - -static inline void list_del_node(struct ocrdma_list_node *entry) -{ - __list_del_node(entry->prev, entry->next); - entry->next = entry->prev = 0; -} - -#define list_lock(head) pthread_mutex_lock(&((head)->lock)) -#define list_unlock(head) pthread_mutex_unlock(&((head)->lock)) - -#define list_node(ptr, type, member) \ - ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) - -/** - * list_for_each_node_safe - iterate over a list safe against removal of list entry - * @pos: the &struct ocrdma_list_head to use as a loop counter. - * @n: another &struct ocrdma_list_head to use as temporary storage - * @head: the head for your list. - */ -#define list_for_each_node_safe(pos, n, head) \ - for (pos = (head)->node.next, n = pos->next; pos != &((head)->node); \ - pos = n, n = pos->next) - -#endif /* __OCRDMA_LIST_H__ */ diff --git a/libocrdma/src/ocrdma_main.c b/libocrdma/src/ocrdma_main.c index 5c494d842..064ecb318 100644 --- a/libocrdma/src/ocrdma_main.c +++ b/libocrdma/src/ocrdma_main.c @@ -46,7 +46,7 @@ #include "ocrdma_main.h" #include "ocrdma_abi.h" -#include "ocrdma_list.h" +#include #include #include @@ -68,7 +68,8 @@ struct { UCNA(EMULEX, GEN1), UCNA(EMULEX, GEN2), UCNA(EMULEX, GEN2_VF) }; -static DBLY_LIST_HEAD(ocrdma_dev_list); +static LIST_HEAD(ocrdma_dev_list); +static pthread_mutex_t ocrdma_dev_list_lock = PTHREAD_MUTEX_INITIALIZER; static struct ibv_context *ocrdma_alloc_context(struct ibv_device *, int); static void ocrdma_free_context(struct ibv_context *); @@ -222,10 +223,10 @@ struct ibv_device *ocrdma_driver_init(const char *uverbs_sys_path, pthread_mutex_init(&dev->dev_lock, NULL); pthread_spin_init(&dev->flush_q_lock, PTHREAD_PROCESS_PRIVATE); dev->ibv_dev.ops = ocrdma_dev_ops; - INIT_DBLY_LIST_NODE(&dev->entry); - list_lock(&ocrdma_dev_list); - list_add_node_tail(&dev->entry, &ocrdma_dev_list); - list_unlock(&ocrdma_dev_list); + list_node_init(&dev->entry); + pthread_mutex_lock(&ocrdma_dev_list_lock); + list_add_tail(&ocrdma_dev_list, &dev->entry); + pthread_mutex_unlock(&ocrdma_dev_list_lock); return &dev->ibv_dev; qp_err: free(dev); @@ -244,14 +245,13 @@ void ocrdma_register_driver(void) static __attribute__ ((destructor)) void ocrdma_unregister_driver(void) { - struct ocrdma_list_node *cur, *tmp; struct ocrdma_device *dev; - list_lock(&ocrdma_dev_list); - list_for_each_node_safe(cur, tmp, &ocrdma_dev_list) { - dev = list_node(cur, struct ocrdma_device, entry); + struct ocrdma_device *dev_tmp; + pthread_mutex_lock(&ocrdma_dev_list_lock); + list_for_each_safe(&ocrdma_dev_list, dev, dev_tmp, entry) { pthread_mutex_destroy(&dev->dev_lock); pthread_spin_destroy(&dev->flush_q_lock); - list_del_node(&dev->entry); + list_del(&dev->entry); /* * Avoid freeing the dev here since MPI get SIGSEGV * in few error cases because of reference to ib_dev @@ -260,5 +260,5 @@ void ocrdma_unregister_driver(void) */ /* free(dev); */ } - list_unlock(&ocrdma_dev_list); + pthread_mutex_unlock(&ocrdma_dev_list_lock); } diff --git a/libocrdma/src/ocrdma_main.h b/libocrdma/src/ocrdma_main.h index c81188b77..b8be6e514 100644 --- a/libocrdma/src/ocrdma_main.h +++ b/libocrdma/src/ocrdma_main.h @@ -42,7 +42,7 @@ #include #include -#include "ocrdma_list.h" +#include #define ocrdma_err(format, arg...) printf(format, ##arg) @@ -58,7 +58,7 @@ struct ocrdma_device { struct ocrdma_qp **qp_tbl; pthread_mutex_t dev_lock; pthread_spinlock_t flush_q_lock; - struct ocrdma_list_node entry; + struct list_node entry; int id; int gen; uint32_t wqe_size; @@ -106,8 +106,8 @@ struct ocrdma_cq { uint8_t deferred_arm; uint8_t deferred_sol; uint8_t first_arm; - struct ocrdma_list_head sq_head; - struct ocrdma_list_head rq_head; + struct list_head sq_head; + struct list_head rq_head; }; enum { @@ -203,8 +203,8 @@ struct ocrdma_qp { enum ibv_qp_type qp_type; enum ocrdma_qp_state state; - struct ocrdma_list_node sq_entry; - struct ocrdma_list_node rq_entry; + struct list_node sq_entry; + struct list_node rq_entry; uint16_t id; uint16_t rsvd; uint32_t db_shift; diff --git a/libocrdma/src/ocrdma_verbs.c b/libocrdma/src/ocrdma_verbs.c index 606262606..413c70618 100644 --- a/libocrdma/src/ocrdma_verbs.c +++ b/libocrdma/src/ocrdma_verbs.c @@ -51,7 +51,7 @@ #include "ocrdma_main.h" #include "ocrdma_abi.h" -#include "ocrdma_list.h" +#include static void ocrdma_ring_cq_db(struct ocrdma_cq *cq, uint32_t armed, int solicited, uint32_t num_cqe); @@ -307,8 +307,8 @@ static struct ibv_cq *ocrdma_create_cq_common(struct ibv_context *context, ocrdma_ring_cq_db(cq, 0, 0, 0); } cq->ibv_cq.cqe = cqe; - INIT_DBLY_LIST_HEAD(&cq->sq_head); - INIT_DBLY_LIST_HEAD(&cq->rq_head); + list_head_init(&cq->sq_head); + list_head_init(&cq->rq_head); return &cq->ibv_cq; cq_err2: (void)ibv_cmd_destroy_cq(&cq->ibv_cq); @@ -621,8 +621,8 @@ struct ibv_qp *ocrdma_create_qp(struct ibv_pd *pd, } } qp->state = OCRDMA_QPS_RST; - INIT_DBLY_LIST_NODE(&qp->sq_entry); - INIT_DBLY_LIST_NODE(&qp->rq_entry); + list_node_init(&qp->sq_entry); + list_node_init(&qp->rq_entry); return &qp->ibv_qp; map_err: @@ -663,10 +663,9 @@ static int ocrdma_is_qp_in_sq_flushlist(struct ocrdma_cq *cq, struct ocrdma_qp *qp) { struct ocrdma_qp *list_qp; - struct ocrdma_list_node *cur, *tmp; + struct ocrdma_qp *list_qp_tmp; int found = 0; - list_for_each_node_safe(cur, tmp, &cq->sq_head) { - list_qp = list_node(cur, struct ocrdma_qp, sq_entry); + list_for_each_safe(&cq->sq_head, list_qp, list_qp_tmp, sq_entry) { if (qp == list_qp) { found = 1; break; @@ -679,10 +678,9 @@ static int ocrdma_is_qp_in_rq_flushlist(struct ocrdma_cq *cq, struct ocrdma_qp *qp) { struct ocrdma_qp *list_qp; - struct ocrdma_list_node *cur, *tmp; + struct ocrdma_qp *list_qp_tmp; int found = 0; - list_for_each_node_safe(cur, tmp, &cq->rq_head) { - list_qp = list_node(cur, struct ocrdma_qp, rq_entry); + list_for_each_safe(&cq->rq_head, list_qp, list_qp_tmp, rq_entry) { if (qp == list_qp) { found = 1; break; @@ -708,11 +706,11 @@ static void ocrdma_del_flush_qp(struct ocrdma_qp *qp) pthread_spin_lock(&dev->flush_q_lock); found = ocrdma_is_qp_in_sq_flushlist(qp->sq_cq, qp); if (found) - list_del_node(&qp->sq_entry); + list_del(&qp->sq_entry); if (!qp->srq) { found = ocrdma_is_qp_in_rq_flushlist(qp->rq_cq, qp); if (found) - list_del_node(&qp->rq_entry); + list_del(&qp->rq_entry); } pthread_spin_unlock(&dev->flush_q_lock); } @@ -724,11 +722,11 @@ static void ocrdma_flush_qp(struct ocrdma_qp *qp) pthread_spin_lock(&qp->dev->flush_q_lock); found = ocrdma_is_qp_in_sq_flushlist(qp->sq_cq, qp); if (!found) - list_add_node_tail(&qp->sq_entry, &qp->sq_cq->sq_head); + list_add_tail(&qp->sq_cq->sq_head, &qp->sq_entry); if (!qp->srq) { found = ocrdma_is_qp_in_rq_flushlist(qp->rq_cq, qp); if (!found) - list_add_node_tail(&qp->rq_entry, &qp->rq_cq->rq_head); + list_add_tail(&qp->rq_cq->rq_head, &qp->rq_entry); } pthread_spin_unlock(&qp->dev->flush_q_lock); } @@ -2034,7 +2032,7 @@ int ocrdma_poll_cq(struct ibv_cq *ibcq, int num_entries, struct ibv_wc *wc) int cqes_to_poll = num_entries; int num_os_cqe = 0, err_cqes = 0; struct ocrdma_qp *qp; - struct ocrdma_list_node *cur, *tmp; + struct ocrdma_qp *qp_tmp; cq = get_ocrdma_cq(ibcq); pthread_spin_lock(&cq->cq_lock); @@ -2045,8 +2043,7 @@ int ocrdma_poll_cq(struct ibv_cq *ibcq, int num_entries, struct ibv_wc *wc) if (cqes_to_poll) { wc = wc + num_os_cqe; pthread_spin_lock(&cq->dev->flush_q_lock); - list_for_each_node_safe(cur, tmp, &cq->sq_head) { - qp = list_node(cur, struct ocrdma_qp, sq_entry); + list_for_each_safe(&cq->sq_head, qp, qp_tmp, sq_entry) { if (cqes_to_poll == 0) break; err_cqes = ocrdma_add_err_cqe(cq, cqes_to_poll, qp, wc); diff --git a/librdmacm/examples/CMakeLists.txt b/librdmacm/examples/CMakeLists.txt index 31c960638..39971754f 100644 --- a/librdmacm/examples/CMakeLists.txt +++ b/librdmacm/examples/CMakeLists.txt @@ -4,40 +4,40 @@ add_library(rdmacm_tools STATIC ) rdma_executable(cmtime cmtime.c) -target_link_libraries(cmtime rdmacm ${CMAKE_THREAD_LIBS_INIT} rdmacm_tools) +target_link_libraries(cmtime LINK_PRIVATE rdmacm ${CMAKE_THREAD_LIBS_INIT} rdmacm_tools) rdma_executable(mckey mckey.c) -target_link_libraries(mckey rdmacm ${CMAKE_THREAD_LIBS_INIT}) +target_link_libraries(mckey LINK_PRIVATE rdmacm ${CMAKE_THREAD_LIBS_INIT}) rdma_executable(rcopy rcopy.c) -target_link_libraries(rcopy rdmacm) +target_link_libraries(rcopy LINK_PRIVATE rdmacm) rdma_executable(rdma_client rdma_client.c) -target_link_libraries(rdma_client rdmacm) +target_link_libraries(rdma_client LINK_PRIVATE rdmacm) rdma_executable(rdma_server rdma_server.c) -target_link_libraries(rdma_server rdmacm) +target_link_libraries(rdma_server LINK_PRIVATE rdmacm) rdma_executable(rdma_xclient rdma_xclient.c) -target_link_libraries(rdma_xclient rdmacm) +target_link_libraries(rdma_xclient LINK_PRIVATE rdmacm) rdma_executable(rdma_xserver rdma_xserver.c) -target_link_libraries(rdma_xserver rdmacm) +target_link_libraries(rdma_xserver LINK_PRIVATE rdmacm) rdma_executable(riostream riostream.c) -target_link_libraries(riostream rdmacm rdmacm_tools) +target_link_libraries(riostream LINK_PRIVATE rdmacm rdmacm_tools) rdma_executable(rping rping.c) -target_link_libraries(rping rdmacm ${CMAKE_THREAD_LIBS_INIT}) +target_link_libraries(rping LINK_PRIVATE rdmacm ${CMAKE_THREAD_LIBS_INIT}) rdma_executable(rstream rstream.c) -target_link_libraries(rstream rdmacm rdmacm_tools) +target_link_libraries(rstream LINK_PRIVATE rdmacm rdmacm_tools) rdma_executable(ucmatose cmatose.c) -target_link_libraries(ucmatose rdmacm rdmacm_tools) +target_link_libraries(ucmatose LINK_PRIVATE rdmacm rdmacm_tools) rdma_executable(udaddy udaddy.c) -target_link_libraries(udaddy rdmacm rdmacm_tools) +target_link_libraries(udaddy LINK_PRIVATE rdmacm rdmacm_tools) rdma_executable(udpong udpong.c) -target_link_libraries(udpong rdmacm rdmacm_tools) +target_link_libraries(udpong LINK_PRIVATE rdmacm rdmacm_tools) diff --git a/librdmacm/src/cma.h b/librdmacm/src/cma.h index 98eba8dc2..68abe54fc 100644 --- a/librdmacm/src/cma.h +++ b/librdmacm/src/cma.h @@ -47,6 +47,8 @@ #include #include +#include + #ifdef INCLUDE_VALGRIND # include # ifndef VALGRIND_MAKE_MEM_DEFINED @@ -68,15 +70,6 @@ static inline uint64_t htonll(uint64_t x) { return x; } static inline uint64_t ntohll(uint64_t x) { return x; } #endif -#define max(a, b) ((a) > (b) ? a : b) -#define min(a, b) ((a) < (b) ? a : b) - -#ifndef container_of -#define container_of(ptr, type, field) \ - ((type *) ((void *)ptr - offsetof(type, field))) -#endif - - /* * Fast synchronization for low contention locking. */ diff --git a/librdmacm/src/rsocket.c b/librdmacm/src/rsocket.c index 818505fbe..0204f0d00 100644 --- a/librdmacm/src/rsocket.c +++ b/librdmacm/src/rsocket.c @@ -3294,10 +3294,10 @@ static void rs_copy_addr(struct sockaddr *dst, struct sockaddr *src, socklen_t * socklen_t size; if (src->sa_family == AF_INET) { - size = min(*len, sizeof(struct sockaddr_in)); + size = min_t(socklen_t, *len, sizeof(struct sockaddr_in)); *len = sizeof(struct sockaddr_in); } else { - size = min(*len, sizeof(struct sockaddr_in6)); + size = min_t(socklen_t, *len, sizeof(struct sockaddr_in6)); *len = sizeof(struct sockaddr_in6); } memcpy(dst, src, size); @@ -3472,15 +3472,18 @@ int rsetsockopt(int socket, int level, int optname, switch (optname) { case RDMA_SQSIZE: - rs->sq_size = min((*(uint32_t *) optval), RS_QP_MAX_SIZE); + rs->sq_size = min_t(uint32_t, (*(uint32_t *)optval), + RS_QP_MAX_SIZE); ret = 0; break; case RDMA_RQSIZE: - rs->rq_size = min((*(uint32_t *) optval), RS_QP_MAX_SIZE); + rs->rq_size = min_t(uint32_t, (*(uint32_t *)optval), + RS_QP_MAX_SIZE); ret = 0; break; case RDMA_INLINE: - rs->sq_inline = min(*(uint32_t *) optval, RS_QP_MAX_SIZE); + rs->sq_inline = min_t(uint32_t, *(uint32_t *)optval, + RS_QP_MAX_SIZE); ret = 0; break; case RDMA_IOMAPSIZE: diff --git a/srp_daemon/srp_daemon/CMakeLists.txt b/srp_daemon/srp_daemon/CMakeLists.txt index 84d740441..b02725bdc 100644 --- a/srp_daemon/srp_daemon/CMakeLists.txt +++ b/srp_daemon/srp_daemon/CMakeLists.txt @@ -5,7 +5,7 @@ rdma_sbin_executable(srp_daemon srp_handle_traps.c srp_sync.c ) -target_link_libraries(srp_daemon +target_link_libraries(srp_daemon LINK_PRIVATE ibverbs ibumad ${RT_LIBRARIES}