123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- // SPDX-License-Identifier: GPL-2.0+
- /*
- * Helper functions to sync execution between parent and child processes.
- *
- * Copyright 2018, Thiago Jung Bauermann, IBM Corporation.
- */
- #include <stdio.h>
- #include <stdbool.h>
- #include <semaphore.h>
- /*
- * Information in a shared memory location for synchronization between child and
- * parent.
- */
- struct child_sync {
- /* The parent waits on this semaphore. */
- sem_t sem_parent;
- /* If true, the child should give up as well. */
- bool parent_gave_up;
- /* The child waits on this semaphore. */
- sem_t sem_child;
- /* If true, the parent should give up as well. */
- bool child_gave_up;
- };
- #define CHILD_FAIL_IF(x, sync) \
- do { \
- if (x) { \
- fprintf(stderr, \
- "[FAIL] Test FAILED on line %d\n", __LINE__); \
- (sync)->child_gave_up = true; \
- prod_parent(sync); \
- return 1; \
- } \
- } while (0)
- #define PARENT_FAIL_IF(x, sync) \
- do { \
- if (x) { \
- fprintf(stderr, \
- "[FAIL] Test FAILED on line %d\n", __LINE__); \
- (sync)->parent_gave_up = true; \
- prod_child(sync); \
- return 1; \
- } \
- } while (0)
- #define PARENT_SKIP_IF_UNSUPPORTED(x, sync) \
- do { \
- if ((x) == -1 && (errno == ENODEV || errno == EINVAL)) { \
- (sync)->parent_gave_up = true; \
- prod_child(sync); \
- SKIP_IF(1); \
- } \
- } while (0)
- int init_child_sync(struct child_sync *sync)
- {
- int ret;
- ret = sem_init(&sync->sem_parent, 1, 0);
- if (ret) {
- perror("Semaphore initialization failed");
- return 1;
- }
- ret = sem_init(&sync->sem_child, 1, 0);
- if (ret) {
- perror("Semaphore initialization failed");
- return 1;
- }
- return 0;
- }
- void destroy_child_sync(struct child_sync *sync)
- {
- sem_destroy(&sync->sem_parent);
- sem_destroy(&sync->sem_child);
- }
- int wait_child(struct child_sync *sync)
- {
- int ret;
- /* Wait until the child prods us. */
- ret = sem_wait(&sync->sem_parent);
- if (ret) {
- perror("Error waiting for child");
- return 1;
- }
- return sync->child_gave_up;
- }
- int prod_child(struct child_sync *sync)
- {
- int ret;
- /* Unblock the child now. */
- ret = sem_post(&sync->sem_child);
- if (ret) {
- perror("Error prodding child");
- return 1;
- }
- return 0;
- }
- int wait_parent(struct child_sync *sync)
- {
- int ret;
- /* Wait until the parent prods us. */
- ret = sem_wait(&sync->sem_child);
- if (ret) {
- perror("Error waiting for parent");
- return 1;
- }
- return sync->parent_gave_up;
- }
- int prod_parent(struct child_sync *sync)
- {
- int ret;
- /* Unblock the parent now. */
- ret = sem_post(&sync->sem_parent);
- if (ret) {
- perror("Error prodding parent");
- return 1;
- }
- return 0;
- }
|