child.h (2649B)
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Helper functions to sync execution between parent and child processes. 4 * 5 * Copyright 2018, Thiago Jung Bauermann, IBM Corporation. 6 */ 7#include <stdio.h> 8#include <stdbool.h> 9#include <semaphore.h> 10 11/* 12 * Information in a shared memory location for synchronization between child and 13 * parent. 14 */ 15struct child_sync { 16 /* The parent waits on this semaphore. */ 17 sem_t sem_parent; 18 19 /* If true, the child should give up as well. */ 20 bool parent_gave_up; 21 22 /* The child waits on this semaphore. */ 23 sem_t sem_child; 24 25 /* If true, the parent should give up as well. */ 26 bool child_gave_up; 27}; 28 29#define CHILD_FAIL_IF(x, sync) \ 30 do { \ 31 if (x) { \ 32 fprintf(stderr, \ 33 "[FAIL] Test FAILED on line %d\n", __LINE__); \ 34 (sync)->child_gave_up = true; \ 35 prod_parent(sync); \ 36 return 1; \ 37 } \ 38 } while (0) 39 40#define PARENT_FAIL_IF(x, sync) \ 41 do { \ 42 if (x) { \ 43 fprintf(stderr, \ 44 "[FAIL] Test FAILED on line %d\n", __LINE__); \ 45 (sync)->parent_gave_up = true; \ 46 prod_child(sync); \ 47 return 1; \ 48 } \ 49 } while (0) 50 51#define PARENT_SKIP_IF_UNSUPPORTED(x, sync) \ 52 do { \ 53 if ((x) == -1 && (errno == ENODEV || errno == EINVAL)) { \ 54 (sync)->parent_gave_up = true; \ 55 prod_child(sync); \ 56 SKIP_IF(1); \ 57 } \ 58 } while (0) 59 60int init_child_sync(struct child_sync *sync) 61{ 62 int ret; 63 64 ret = sem_init(&sync->sem_parent, 1, 0); 65 if (ret) { 66 perror("Semaphore initialization failed"); 67 return 1; 68 } 69 70 ret = sem_init(&sync->sem_child, 1, 0); 71 if (ret) { 72 perror("Semaphore initialization failed"); 73 return 1; 74 } 75 76 return 0; 77} 78 79void destroy_child_sync(struct child_sync *sync) 80{ 81 sem_destroy(&sync->sem_parent); 82 sem_destroy(&sync->sem_child); 83} 84 85int wait_child(struct child_sync *sync) 86{ 87 int ret; 88 89 /* Wait until the child prods us. */ 90 ret = sem_wait(&sync->sem_parent); 91 if (ret) { 92 perror("Error waiting for child"); 93 return 1; 94 } 95 96 return sync->child_gave_up; 97} 98 99int prod_child(struct child_sync *sync) 100{ 101 int ret; 102 103 /* Unblock the child now. */ 104 ret = sem_post(&sync->sem_child); 105 if (ret) { 106 perror("Error prodding child"); 107 return 1; 108 } 109 110 return 0; 111} 112 113int wait_parent(struct child_sync *sync) 114{ 115 int ret; 116 117 /* Wait until the parent prods us. */ 118 ret = sem_wait(&sync->sem_child); 119 if (ret) { 120 perror("Error waiting for parent"); 121 return 1; 122 } 123 124 return sync->parent_gave_up; 125} 126 127int prod_parent(struct child_sync *sync) 128{ 129 int ret; 130 131 /* Unblock the parent now. */ 132 ret = sem_post(&sync->sem_parent); 133 if (ret) { 134 perror("Error prodding parent"); 135 return 1; 136 } 137 138 return 0; 139}