Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Helper functions to sync execution between parent and child processes.
0004  *
0005  * Copyright 2018, Thiago Jung Bauermann, IBM Corporation.
0006  */
0007 #include <stdio.h>
0008 #include <stdbool.h>
0009 #include <semaphore.h>
0010 
0011 /*
0012  * Information in a shared memory location for synchronization between child and
0013  * parent.
0014  */
0015 struct child_sync {
0016     /* The parent waits on this semaphore. */
0017     sem_t sem_parent;
0018 
0019     /* If true, the child should give up as well. */
0020     bool parent_gave_up;
0021 
0022     /* The child waits on this semaphore. */
0023     sem_t sem_child;
0024 
0025     /* If true, the parent should give up as well. */
0026     bool child_gave_up;
0027 };
0028 
0029 #define CHILD_FAIL_IF(x, sync)                      \
0030     do {                                \
0031         if (x) {                        \
0032             fprintf(stderr,                 \
0033                 "[FAIL] Test FAILED on line %d\n", __LINE__); \
0034             (sync)->child_gave_up = true;           \
0035             prod_parent(sync);              \
0036             return 1;                   \
0037         }                           \
0038     } while (0)
0039 
0040 #define PARENT_FAIL_IF(x, sync)                     \
0041     do {                                \
0042         if (x) {                        \
0043             fprintf(stderr,                 \
0044                 "[FAIL] Test FAILED on line %d\n", __LINE__); \
0045             (sync)->parent_gave_up = true;          \
0046             prod_child(sync);               \
0047             return 1;                   \
0048         }                           \
0049     } while (0)
0050 
0051 #define PARENT_SKIP_IF_UNSUPPORTED(x, sync)             \
0052     do {                                \
0053         if ((x) == -1 && (errno == ENODEV || errno == EINVAL)) { \
0054             (sync)->parent_gave_up = true;          \
0055             prod_child(sync);               \
0056             SKIP_IF(1);                 \
0057         }                           \
0058     } while (0)
0059 
0060 int init_child_sync(struct child_sync *sync)
0061 {
0062     int ret;
0063 
0064     ret = sem_init(&sync->sem_parent, 1, 0);
0065     if (ret) {
0066         perror("Semaphore initialization failed");
0067         return 1;
0068     }
0069 
0070     ret = sem_init(&sync->sem_child, 1, 0);
0071     if (ret) {
0072         perror("Semaphore initialization failed");
0073         return 1;
0074     }
0075 
0076     return 0;
0077 }
0078 
0079 void destroy_child_sync(struct child_sync *sync)
0080 {
0081     sem_destroy(&sync->sem_parent);
0082     sem_destroy(&sync->sem_child);
0083 }
0084 
0085 int wait_child(struct child_sync *sync)
0086 {
0087     int ret;
0088 
0089     /* Wait until the child prods us. */
0090     ret = sem_wait(&sync->sem_parent);
0091     if (ret) {
0092         perror("Error waiting for child");
0093         return 1;
0094     }
0095 
0096     return sync->child_gave_up;
0097 }
0098 
0099 int prod_child(struct child_sync *sync)
0100 {
0101     int ret;
0102 
0103     /* Unblock the child now. */
0104     ret = sem_post(&sync->sem_child);
0105     if (ret) {
0106         perror("Error prodding child");
0107         return 1;
0108     }
0109 
0110     return 0;
0111 }
0112 
0113 int wait_parent(struct child_sync *sync)
0114 {
0115     int ret;
0116 
0117     /* Wait until the parent prods us. */
0118     ret = sem_wait(&sync->sem_child);
0119     if (ret) {
0120         perror("Error waiting for parent");
0121         return 1;
0122     }
0123 
0124     return sync->parent_gave_up;
0125 }
0126 
0127 int prod_parent(struct child_sync *sync)
0128 {
0129     int ret;
0130 
0131     /* Unblock the parent now. */
0132     ret = sem_post(&sync->sem_parent);
0133     if (ret) {
0134         perror("Error prodding parent");
0135         return 1;
0136     }
0137 
0138     return 0;
0139 }