cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

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}