| | |
| | | cmake_minimum_required(VERSION 3.5) |
| | | |
| | | # set the project name and version |
| | | project(B_BUS VERSION 3.0) |
| | | project(B_BUS VERSION 2.2) |
| | | |
| | | # specify the C++ standard |
| | | set(CMAKE_CXX_STANDARD 11) |
| | |
| | | |
| | | |
| | | list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/include/usgcommon") |
| | | list(APPEND EXTRA_LIBS ${PROJECT_SOURCE_DIR}/lib/libusgcommon.a pthread) |
| | | list(APPEND EXTRA_LIBS ${PROJECT_SOURCE_DIR}/lib/libusgcommon.a pthread rt) |
| | | |
| | | add_subdirectory(${PROJECT_SOURCE_DIR}/src) |
| | | add_subdirectory(${PROJECT_SOURCE_DIR}/test) |
| | | add_subdirectory(${PROJECT_SOURCE_DIR}/test_net_socket) |
| | | add_subdirectory(${PROJECT_SOURCE_DIR}/test_net_socket) |
| | | # build api doc |
| | | if (CMAKE_BUILD_TYPE MATCHES "^[Rr]elease") |
| | | # build the docs |
| | | add_subdirectory(${PROJECT_SOURCE_DIR}/doc) |
| | | endif() |
| | |
| | | # -DBUILD_SHARED_LIBS=ON |
| | | # -DCMAKE_INSTALL_PREFIX=$(pwd/../dest) |
| | | # -DQCA_MAN_INSTALL_DIR:PATH=/usr/share/man |
| | | cmake -DCMAKE_INSTALL_PREFIX="$(pwd)/../dest" -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DSUPPORT_RDMA=OFF .. |
| | | cmake -DCMAKE_INSTALL_PREFIX="$(pwd)/../dest" -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DBUILD_SHARED_LIBS=ON -DSUPPORT_RDMA=OFF .. |
| | | |
| | | cmake --build . |
| | | |
| | | #cmake --build . --target install |
| | | cmake --build . --target install |
| | | |
New file |
| | |
| | | # first we can indicate the documentation build as an option and set it to ON by default |
| | | option(BUILD_DOC "Build documentation" ON) |
| | | |
| | | # check if Doxygen is installed |
| | | find_package(Doxygen) |
| | | if (DOXYGEN_FOUND) |
| | | # set input and output files |
| | | set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in) |
| | | set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) |
| | | |
| | | # request to configure the file |
| | | configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY) |
| | | message("Doxygen build started") |
| | | |
| | | # note the option ALL which allows to build the docs together with the application |
| | | add_custom_target( doc_doxygen ALL |
| | | COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT} |
| | | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} |
| | | COMMENT "Generating API documentation with Doxygen" |
| | | VERBATIM ) |
| | | |
| | | install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/api" |
| | | DESTINATION doc |
| | | ) |
| | | |
| | | else (DOXYGEN_FOUND) |
| | | message("Doxygen need to be installed to generate the doxygen documentation. To install type common `sudo apt install -y doxygen texlive-latex-base graphviz` ") |
| | | endif (DOXYGEN_FOUND) |
File was renamed from Doxyfile |
| | |
| | | # entered, it will be relative to the location where doxygen was started. If |
| | | # left blank the current directory will be used. |
| | | |
| | | OUTPUT_DIRECTORY = build/doc |
| | | OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@/api |
| | | |
| | | # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- |
| | | # directories (in 2 levels) under the output directory of each output format and |
| | |
| | | # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING |
| | | # Note: If this tag is empty the current directory is searched. |
| | | |
| | | INPUT = src |
| | | INPUT = @CMAKE_SOURCE_DIR@/src @CMAKE_CURRENT_SOURCE_DIR@ |
| | | |
| | | # This tag can be used to specify the character encoding of the source files |
| | | # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses |
| | |
| | | ## 2 æ ééåï¼Free Lockï¼çå®ç° |
| | | æ éé忝ç¨ç»ç²åº¦çååéå®ç°çï¼å¤è¿ç¨æä½æ¶æ é»å¡å¹¶åæ§è½é«ãç½ä¸æäºè±å
«é¨çç¸å
³ç®æ³å®ç°ãæå¯¹æ¯äºä¸ä¸ï¼å³å®éç¨ä¸é¢çè¿ä¸ªãè¿ä¸ªç®æ³æ§è½å¥½æ¯ä¸æ¹é¢ï¼å®åæ¶ä¹è§£å³äºéå为空æ¶å¹¶åæä½å¯è½åºç°çé®é¢ï¼ä»¥åABAçé®é¢ã |
| | | |
| | |  |
| | |  |
| | | |
| | | ## 3 ç产è
æ¶è´¹è
ä¹é´çåä½ |
| | | |
| | |
| | | # install rules |
| | | install(TARGETS shm_queue DESTINATION lib) |
| | | install(FILES |
| | | socket/socket_def.h |
| | | socket/net_conn_pool.h |
| | | socket/bus_server_socket.h |
| | | socket/shm_socket.h |
| | | socket/net_mod_socket.h |
| | | socket/shm_stream_mod_socket.h |
| | | socket/net_mod_server_socket_wrapper.h |
| | | socket/net_mod_socket_io.h |
| | | socket/net_mod_server_socket.h |
| | | socket/shm_mod_socket.h |
| | | socket/net_mod_socket_wrapper.h |
| | | socket/bus_server_socket_wrapper.h |
| | | key_def.h |
| | | bus_error.h |
| | | logger_factory.h |
| | | queue/linked_lock_free_queue.h |
| | | queue/array_lock_free_queue2.h |
| | | queue/array_lock_free_queue.h |
| | | queue/shm_queue.h |
| | | queue/shm_queue_wrapper.h |
| | | queue/lock_free_queue.h |
| | | shm/hashtable.h |
| | | shm/mem_pool.h |
| | | shm/mm.h |
| | | shm/shm_allocator.h |
| | | shm/shm_mm_wraper.h |
| | | socket/socket_def.h |
| | | socket/net_conn_pool.h |
| | | socket/bus_server_socket.h |
| | | socket/shm_socket.h |
| | | socket/net_mod_socket.h |
| | | socket/shm_stream_mod_socket.h |
| | | socket/net_mod_server_socket_wrapper.h |
| | | socket/net_mod_socket_io.h |
| | | socket/net_mod_server_socket.h |
| | | socket/shm_mod_socket.h |
| | | socket/net_mod_socket_wrapper.h |
| | | socket/bus_server_socket_wrapper.h |
| | | key_def.h |
| | | bus_error.h |
| | | px_sem_util.h |
| | | logger_factory.h |
| | | queue/linked_lock_free_queue.h |
| | | queue/array_lock_free_queue2.h |
| | | queue/array_lock_free_queue.h |
| | | queue/shm_queue.h |
| | | queue/lock_free_queue.h |
| | | shm/hashtable.h |
| | | shm/mem_pool.h |
| | | shm/mm.h |
| | | shm/shm_mm_wrapper.h |
| | | shm/shm_allocator.h |
| | | |
| | | DESTINATION include) |
| | | |
| | | install(FILES "${PROJECT_BINARY_DIR}/src/BusConfig.h" |
| | | install(FILES "${PROJECT_BINARY_DIR}/src/bus_config.h" |
| | | DESTINATION include |
| | | ) |
| | |
| | | # add the executable |
| | | add_executable(test1 test1.cpp ) |
| | | target_link_libraries(test1 PUBLIC ${EXTRA_LIBS} ) |
| | | |
| | | target_include_directories(test1 PUBLIC |
| | | target_link_libraries(test1 PRIVATE ${EXTRA_LIBS} ) |
| | | target_include_directories(test1 PRIVATE |
| | | "${PROJECT_BINARY_DIR}" |
| | | ${EXTRA_INCLUDES} |
| | | ) |
| | | |
| | | |
| | | add_executable(futex_demo futex_demo.cpp ) |
| | | target_link_libraries(futex_demo PRIVATE ${EXTRA_LIBS} ) |
| | | target_include_directories(futex_demo PRIVATE |
| | | "${PROJECT_BINARY_DIR}" |
| | | ${EXTRA_INCLUDES} |
| | | ) |
| | | |
| | | |
| | | add_executable(futex_test futex_test.cpp ) |
| | | target_link_libraries(futex_test PRIVATE ${EXTRA_LIBS} ) |
| | | target_include_directories(futex_test PRIVATE |
| | | "${PROJECT_BINARY_DIR}" |
| | | ${EXTRA_INCLUDES} |
| | | ) |
| | | |
| | | |
| | | # add the install targets |
| | | install(TARGETS test1 DESTINATION bin) |
New file |
| | |
| | | /* futex_demo.c |
| | | |
| | | Usage: futex_demo [nloops] |
| | | (Default: 5) |
| | | |
| | | Demonstrate the use of futexes in a program where parent and child |
| | | use a pair of futexes located inside a shared anonymous mapping to |
| | | synchronize access to a shared resource: the terminal. The two |
| | | processes each write 'num-loops' messages to the terminal and employ |
| | | a synchronization protocol that ensures that they alternate in |
| | | writing messages. |
| | | */ |
| | | #include <stdio.h> |
| | | #include <errno.h> |
| | | #include <stdlib.h> |
| | | #include <unistd.h> |
| | | #include <sys/wait.h> |
| | | #include <sys/mman.h> |
| | | #include <sys/syscall.h> |
| | | #include <linux/futex.h> |
| | | #include <sys/time.h> |
| | | #include "usg_common.h" |
| | | #include <sys/mman.h> |
| | | #include <sys/stat.h> /* For mode constants */ |
| | | #include <fcntl.h> /* For O_* constants */ |
| | | |
| | | |
| | | #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \ |
| | | } while (0) |
| | | |
| | | static int *futex1, *futex2, *iaddr; |
| | | |
| | | static int |
| | | futex(int *uaddr, int futex_op, int val, |
| | | const struct timespec *timeout, int *uaddr2, int val3) |
| | | { |
| | | return syscall(SYS_futex, uaddr, futex_op, val, |
| | | timeout, uaddr, val3); |
| | | } |
| | | |
| | | /* Acquire the futex pointed to by 'futexp': wait for its value to |
| | | become 1, and then set the value to 0. */ |
| | | |
| | | static void |
| | | fwait(int *futexp) |
| | | { |
| | | int s; |
| | | |
| | | /* __sync_bool_compare_and_swap(ptr, oldval, newval) is a gcc |
| | | built-in function. It atomically performs the equivalent of: |
| | | |
| | | if (*ptr == oldval) |
| | | *ptr = newval; |
| | | |
| | | It returns true if the test yielded true and *ptr was updated. |
| | | The alternative here would be to employ the equivalent atomic |
| | | machine-language instructions. For further information, see |
| | | the GCC Manual. */ |
| | | while (1) { |
| | | |
| | | /* Is the futex available? */ |
| | | |
| | | if (__sync_bool_compare_and_swap(futexp, 1, 0)) |
| | | break; /* Yes */ |
| | | |
| | | /* Futex is not available; wait */ |
| | | |
| | | s = futex(futexp, FUTEX_WAIT, 0, NULL, NULL, 0); |
| | | if (s == -1 && errno != EAGAIN) |
| | | errExit("futex-FUTEX_WAIT"); |
| | | } |
| | | } |
| | | |
| | | /* Release the futex pointed to by 'futexp': if the futex currently |
| | | has the value 0, set its value to 1 and the wake any futex waiters, |
| | | so that if the peer is blocked in fpost(), it can proceed. */ |
| | | |
| | | static void |
| | | fpost(int *futexp) |
| | | { |
| | | int s; |
| | | |
| | | /* __sync_bool_compare_and_swap() was described in comments above */ |
| | | |
| | | if (__sync_bool_compare_and_swap(futexp, 0, 1)) { |
| | | |
| | | s = futex(futexp, FUTEX_WAKE, 1, NULL, NULL, 0); |
| | | if (s == -1) |
| | | errExit("futex-FUTEX_WAKE"); |
| | | } |
| | | } |
| | | |
| | | int |
| | | main(int argc, char *argv[]) |
| | | { |
| | | pid_t childPid; |
| | | int j, nloops; |
| | | |
| | | int flags, opt, fd; |
| | | mode_t perms; |
| | | size_t size; |
| | | |
| | | setbuf(stdout, NULL); |
| | | |
| | | nloops = (argc > 1) ? atoi(argv[1]) : 5; |
| | | |
| | | flags = O_RDWR | O_CREAT | O_EXCL; |
| | | perms = S_IRUSR | S_IWUSR; |
| | | size = sizeof(int) * 2; |
| | | |
| | | fd = shm_open("futex_demo", flags, perms); |
| | | if (fd == -1) |
| | | errExit("shm_open"); |
| | | if (ftruncate(fd, size) == -1) |
| | | errExit("ftruncate"); |
| | | |
| | | /* Create a shared anonymous mapping that will hold the futexes. |
| | | Since the futexes are being shared between processes, we |
| | | subsequently use the "shared" futex operations (i.e., not the |
| | | ones suffixed "_PRIVATE") */ |
| | | |
| | | iaddr = (int *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, fd, 0); |
| | | if (iaddr == MAP_FAILED) |
| | | errExit("mmap"); |
| | | |
| | | futex1 = &iaddr[0]; |
| | | futex2 = &iaddr[1]; |
| | | |
| | | *futex1 = 0; /* State: unavailable */ |
| | | *futex2 = 1; /* State: available */ |
| | | |
| | | /* Create a child process that inherits the shared anonymous |
| | | mapping */ |
| | | |
| | | childPid = fork(); |
| | | if (childPid == -1) |
| | | errExit("fork"); |
| | | |
| | | if (childPid == 0) { /* Child */ |
| | | for (j = 0; j < nloops; j++) { |
| | | fwait(futex1); |
| | | printf("Child (%ld) %d\n", (long) getpid(), j); |
| | | fpost(futex2); |
| | | } |
| | | |
| | | exit(EXIT_SUCCESS); |
| | | } |
| | | |
| | | /* Parent falls through to here */ |
| | | |
| | | for (j = 0; j < nloops; j++) { |
| | | fwait(futex2); |
| | | printf("Parent (%ld) %d\n", (long) getpid(), j); |
| | | fpost(futex1); |
| | | } |
| | | |
| | | wait(NULL); |
| | | |
| | | exit(EXIT_SUCCESS); |
| | | } |
| | | |
New file |
| | |
| | | /* futex_demo.c |
| | | |
| | | Usage: futex_demo [nloops] |
| | | (Default: 5) |
| | | |
| | | Demonstrate the use of futexes in a program where parent and child |
| | | use a pair of futexes located inside a shared anonymous mapping to |
| | | synchronize access to a shared resource: the terminal. The two |
| | | processes each write 'num-loops' messages to the terminal and employ |
| | | a synchronization protocol that ensures that they alternate in |
| | | writing messages. |
| | | */ |
| | | #include <stdio.h> |
| | | #include <errno.h> |
| | | #include <stdlib.h> |
| | | #include <unistd.h> |
| | | #include <sys/wait.h> |
| | | #include <sys/mman.h> |
| | | #include <sys/syscall.h> |
| | | #include <linux/futex.h> |
| | | #include <sys/time.h> |
| | | #include "usg_common.h" |
| | | #include <sys/mman.h> |
| | | #include <sys/stat.h> /* For mode constants */ |
| | | #include <fcntl.h> /* For O_* constants */ |
| | | |
| | | |
| | | #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \ |
| | | } while (0) |
| | | |
| | | static int *futex1, *futex2, *iaddr; |
| | | |
| | | static int |
| | | futex(int *uaddr, int futex_op, int val, |
| | | const struct timespec *timeout, int *uaddr2, int val3) |
| | | { |
| | | return syscall(SYS_futex, uaddr, futex_op, val, |
| | | timeout, uaddr, val3); |
| | | } |
| | | |
| | | /* Acquire the futex pointed to by 'futexp': wait for its value to |
| | | become 1, and then set the value to 0. */ |
| | | |
| | | static void |
| | | fwait(int *futexp) |
| | | { |
| | | int s; |
| | | |
| | | /* __sync_bool_compare_and_swap(ptr, oldval, newval) is a gcc |
| | | built-in function. It atomically performs the equivalent of: |
| | | |
| | | if (*ptr == oldval) |
| | | *ptr = newval; |
| | | |
| | | It returns true if the test yielded true and *ptr was updated. |
| | | The alternative here would be to employ the equivalent atomic |
| | | machine-language instructions. For further information, see |
| | | the GCC Manual. */ |
| | | while (1) { |
| | | |
| | | /* Is the futex available? */ |
| | | |
| | | if (__sync_bool_compare_and_swap(futexp, 1, 0)) |
| | | break; /* Yes */ |
| | | |
| | | /* Futex is not available; wait */ |
| | | |
| | | s = futex(futexp, FUTEX_WAIT, 0, NULL, NULL, 0); |
| | | if (s == -1 && errno != EAGAIN) |
| | | errExit("futex-FUTEX_WAIT"); |
| | | } |
| | | } |
| | | |
| | | /* Release the futex pointed to by 'futexp': if the futex currently |
| | | has the value 0, set its value to 1 and the wake any futex waiters, |
| | | so that if the peer is blocked in fpost(), it can proceed. */ |
| | | |
| | | static void |
| | | fpost(int *futexp) |
| | | { |
| | | int s; |
| | | |
| | | /* __sync_bool_compare_and_swap() was described in comments above */ |
| | | |
| | | if (__sync_bool_compare_and_swap(futexp, 0, 1)) { |
| | | |
| | | s = futex(futexp, FUTEX_WAKE, 1, NULL, NULL, 0); |
| | | if (s == -1) |
| | | errExit("futex-FUTEX_WAKE"); |
| | | } |
| | | } |
| | | |
| | | int |
| | | main(int argc, char *argv[]) |
| | | { |
| | | pid_t childPid; |
| | | int j, nloops; |
| | | |
| | | int opt, fd; |
| | | mode_t perms; |
| | | size_t size; |
| | | bool first = true; |
| | | |
| | | setbuf(stdout, NULL); |
| | | |
| | | nloops = (argc > 1) ? atoi(argv[1]) : 5; |
| | | |
| | | perms = S_IRUSR | S_IWUSR; |
| | | size = sizeof(int) ; |
| | | |
| | | fd = shm_open("futex_test", O_RDWR | O_CREAT | O_EXCL, perms); |
| | | if (fd == -1 && errno == EEXIST) { |
| | | fd = shm_open("futex_test", O_RDWR, perms); |
| | | first = false; |
| | | } |
| | | |
| | | if(fd == -1) { |
| | | errExit("shm_open"); |
| | | } |
| | | if (ftruncate(fd, size) == -1) |
| | | errExit("ftruncate"); |
| | | |
| | | /* Create a shared anonymous mapping that will hold the futexes. |
| | | Since the futexes are being shared between processes, we |
| | | subsequently use the "shared" futex operations (i.e., not the |
| | | ones suffixed "_PRIVATE") */ |
| | | |
| | | iaddr = (int *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); |
| | | if (iaddr == MAP_FAILED) |
| | | errExit("mmap"); |
| | | |
| | | futex1 = iaddr; |
| | | |
| | | if(first) { |
| | | |
| | | *futex1 = 1; |
| | | } |
| | | |
| | | /* State: available */ |
| | | |
| | | fwait(futex1); |
| | | printf("(%ld) è¿å
¥äºæ¥åº\n", (long) getpid()); |
| | | sleep(5); |
| | | fpost(futex1); |
| | | |
| | | exit(EXIT_SUCCESS); |
| | | } |
| | | |
| | |
| | | |
| | | # add the executable |
| | | add_executable(test_net_mod_socket test_net_mod_socket.cpp ${CMAKE_CURRENT_BINARY_DIR}/net_mod_socket.sh) |
| | | target_link_libraries(test_net_mod_socket PUBLIC shm_queue ${EXTRA_LIBS} ) |
| | | target_link_libraries(test_net_mod_socket PRIVATE shm_queue ${EXTRA_LIBS} ) |
| | | |
| | | add_executable(heart_beat heart_beat.cpp ${CMAKE_CURRENT_BINARY_DIR}/heart_beat.sh) |
| | | target_link_libraries(heart_beat PUBLIC shm_queue ) |
| | | # target_link_libraries(heart_beat PUBLIC shm_queue ${EXTRA_LIBS} ) |
| | | target_link_libraries(heart_beat PRIVATE shm_queue ) |
| | | # target_link_libraries(heart_beat PRIVATE shm_queue ${EXTRA_LIBS} ) |
| | | |
| | | |
| | | target_include_directories(test_net_mod_socket PUBLIC |
| | | target_include_directories(test_net_mod_socket PRIVATE |
| | | "${PROJECT_BINARY_DIR}" |
| | | ${EXTRA_INCLUDES} |
| | | ) |