0001
0002
0003
0004
0005
0006
0007 #include <stdio.h>
0008 #include <stdbool.h>
0009 #include <semaphore.h>
0010
0011
0012
0013
0014
0015 struct child_sync {
0016
0017 sem_t sem_parent;
0018
0019
0020 bool parent_gave_up;
0021
0022
0023 sem_t sem_child;
0024
0025
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
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
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
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
0132 ret = sem_post(&sync->sem_parent);
0133 if (ret) {
0134 perror("Error prodding parent");
0135 return 1;
0136 }
0137
0138 return 0;
0139 }