WSL/test/linux/unit_tests/lxtevent.h

226 lines
8.5 KiB
C
Raw Permalink Normal View History

/*++
Copyright (c) Microsoft. All rights reserved.
Module Name:
lxtevent.c
Abstract:
This file contains synchronization event primitive support.
--*/
#include <pthread.h>
//
// Synchronization event usable for synchronizing threads and forked processes.
//
typedef struct _LXT_SYNCHRONIZATION_EVENT
{
pthread_cond_t WaitConditionalVariable;
pthread_condattr_t ConditionVariableAttribute;
pthread_mutex_t Lock;
pthread_mutexattr_t LockAttribute;
int Ready;
int Fail;
} LXT_SYNCHRONIZATION_EVENT, *PLXT_SYNCHRONIZATION_EVENT;
int LxtSynchronizationEventClear(PLXT_SYNCHRONIZATION_EVENT Event);
int LxtSynchronizationEventDestroy(PLXT_SYNCHRONIZATION_EVENT* Event);
int LxtSynchronizationEventFail(PLXT_SYNCHRONIZATION_EVENT Event);
int LxtSynchronizationEventInit(PLXT_SYNCHRONIZATION_EVENT* Event);
int LxtSynchronizationEventReset(PLXT_SYNCHRONIZATION_EVENT Event);
int LxtSynchronizationEventSet(PLXT_SYNCHRONIZATION_EVENT Event);
int LxtSynchronizationEventWait(PLXT_SYNCHRONIZATION_EVENT Event);
//
// Synchronization point based on synchronization event.
//
#define LXT_SYNCHRONIZATION_POINT_DECLARE_FOR(_ChildPidVariable_) \
PLXT_SYNCHRONIZATION_EVENT LxtSync##_ChildPidVariable_##Parent; \
PLXT_SYNCHRONIZATION_EVENT LxtSync##_ChildPidVariable_##Child;
#define LXT_SYNCHRONIZATION_POINT_DECLARE_FOR_STATIC(_ChildPidVariable_) \
static PLXT_SYNCHRONIZATION_EVENT LxtSync##_ChildPidVariable_##Parent; \
static PLXT_SYNCHRONIZATION_EVENT LxtSync##_ChildPidVariable_##Child;
#define LXT_SYNCHRONIZATION_POINT_INIT_SYNCVARS(_ParentVar_, _ChildVar_) \
(_ParentVar_) = NULL; \
(_ChildVar_) = NULL; \
LxtCheckResult(LxtSynchronizationEventInit(&_ParentVar_)); \
LxtCheckResult(LxtSynchronizationEventInit(&_ChildVar_));
#define LXT_SYNCHRONIZATION_POINT_INIT_FOR(_ChildPidVariable_) \
LXT_SYNCHRONIZATION_POINT_INIT_SYNCVARS(LxtSync##_ChildPidVariable_##Parent, LxtSync##_ChildPidVariable_##Child)
#define LXT_SYNCHRONIZATION_POINT_INIT() LXT_SYNCHRONIZATION_POINT_INIT_FOR(ChildPid)
#define LXT_SYNCHRONIZATION_POINT_DESTROY_SYNCVARS(_ParentVar_, _ChildVar_) \
LxtSynchronizationEventDestroy(&(_ParentVar_)); \
LxtSynchronizationEventDestroy(&(_ChildVar_));
#define LXT_SYNCHRONIZATION_POINT_DESTROY_FOR(_ChildPidVariable_) \
LXT_SYNCHRONIZATION_POINT_DESTROY_SYNCVARS(LxtSync##_ChildPidVariable_##Parent, LxtSync##_ChildPidVariable_##Child)
#define LXT_SYNCHRONIZATION_POINT_DESTROY() LXT_SYNCHRONIZATION_POINT_DESTROY_FOR(ChildPid)
#define LXT_SYNCHRONIZATION_POINT_START_SYNCVARS(_ParentVar_, _ChildVar_) \
LxtSynchronizationEventReset(_ChildVar_); \
LxtSynchronizationEventReset(_ParentVar_);
#define LXT_SYNCHRONIZATION_POINT_START_FOR(_ChildPidVariable_) \
LXT_SYNCHRONIZATION_POINT_START_SYNCVARS(LxtSync##_ChildPidVariable_##Child, LxtSync##_ChildPidVariable_##Parent)
#define LXT_SYNCHRONIZATION_POINT_START() LXT_SYNCHRONIZATION_POINT_START_FOR(ChildPid)
#define LXT_SYNCHRONIZATION_POINT_END_SYNCVARS(_ChildId_, _ParentVar_, _ChildVar_, _Destroy_) \
if (((_ChildId_) >= 0) && (Result < 0)) \
{ \
LxtLogError("Failing synchronization points."); \
LxtSynchronizationEventFail(_ChildVar_); \
LxtSynchronizationEventFail(_ParentVar_); \
} \
if ((_ChildId_) > 0) \
{ \
if (TEMP_FAILURE_RETRY(waitpid((_ChildId_), &Status, 0)) >= 0) \
{ \
if (!WIFEXITED(Status)) \
{ \
LxtLogInfo("Child exited uncleanly (Child = %d, Status = %x)", (_ChildId_), Status); \
Result = LXT_RESULT_FAILURE; \
} \
else \
{ \
Result = (int)(char)WEXITSTATUS(Status); \
} \
} \
else \
{ \
Result = errno; \
LxtLogInfo("Failed wait on child %d with errno %d", (_ChildId_), Result); \
} \
if ((Result == LXT_RESULT_SUCCESS) && ((_ChildVar_)->Fail == 1)) \
{ \
LxtLogInfo("Child failed"); \
Result = LXT_RESULT_FAILURE; \
} \
if ((_Destroy_) != FALSE) \
{ \
LXT_SYNCHRONIZATION_POINT_DESTROY_SYNCVARS(_ParentVar_, _ChildVar_) \
} \
} \
else if ((_ChildId_) == 0) \
{ \
_exit(Result); \
}
#define LXT_SYNCHRONIZATION_POINT_END_FOR(_ChildPidVariable_, _Destroy_) \
LXT_SYNCHRONIZATION_POINT_END_SYNCVARS((_ChildPidVariable_), LxtSync##_ChildPidVariable_##Parent, LxtSync##_ChildPidVariable_##Child, _Destroy_)
#define LXT_SYNCHRONIZATION_POINT_END() LXT_SYNCHRONIZATION_POINT_END_FOR(ChildPid, FALSE)
#define LXT_SYNCHRONIZATION_POINT_PTHREAD_END_THREAD_SYNCVARS(_ParentVar_, _ChildVar_) \
if (Result < 0) \
{ \
LxtLogError("Failing synchronization points."); \
LxtSynchronizationEventFail(_ChildVar_); \
LxtSynchronizationEventFail(_ParentVar_); \
}
#define LXT_SYNCHRONIZATION_POINT_PTHREAD_END_THREAD_FOR(_SyncIdVariable_) \
LXT_SYNCHRONIZATION_POINT_PTHREAD_END_THREAD_SYNCVARS(LxtSync##_SyncIdVariable_##Parent, LxtSync##_SyncIdVariable_##Child)
#define LXT_SYNCHRONIZATION_POINT_PTHREAD_END_THREAD() LXT_SYNCHRONIZATION_POINT_PTHREAD_END_THREAD_FOR(ChildPid)
#define LXT_SYNCHRONIZATION_POINT_PTHREAD_END_PARENT_SYNCVARS(_ThreadId_, _ParentVar_, _ChildVar_) \
if (Result < 0) \
{ \
LxtLogError("Failing synchronization points."); \
LxtSynchronizationEventFail(_ChildVar_); \
LxtSynchronizationEventFail(_ParentVar_); \
} \
if (((_ThreadId_) > 0) && (pthread_join((_ThreadId_), &Status) == 0)) \
{ \
if (Status != 0) \
{ \
LxtLogInfo("Thread exited uncleanly (Thread = %d, Status = %x)", (_ThreadId_), (int)(long)Status); \
Result = LXT_RESULT_FAILURE; \
} \
} \
else if ((_ThreadId_) > 0) \
{ \
Result = errno; \
LxtLogInfo("Failed wait on thread %d with errno %d", (_ThreadId_), Result); \
} \
if ((Result == LXT_RESULT_SUCCESS) && ((_ChildVar_)->Fail == 1)) \
{ \
LxtLogInfo("Thread failed"); \
Result = LXT_RESULT_FAILURE; \
}
#define LXT_SYNCHRONIZATION_POINT_PTHREAD_END_PARENT_FOR(_ThreadId_, _SyncIdVariable_) \
LXT_SYNCHRONIZATION_POINT_PTHREAD_END_PARENT_SYNCVARS((_ThreadId_), LxtSync##_SyncIdVariable_##Parent, LxtSync##_SyncIdVariable_##Child)
#define LXT_SYNCHRONIZATION_POINT_PTHREAD_END_PARENT(_ThreadId_) \
LXT_SYNCHRONIZATION_POINT_PTHREAD_END_PARENT_FOR(_ThreadId_, ChildPid)
#define LXT_SYNCHRONIZATION_POINT_CLEAR_FOR(_ChildPidVariable_) \
if (Result < 0) \
{ \
LxtCheckResult(LxtSynchronizationEventClear(LxtSync##_ChildPidVariable_##Child)); \
LxtCheckResult(LxtSynchronizationEventClear(LxtSync##_ChildPidVariable_##Parent)); \
}
#define LXT_SYNCHRONIZATION_POINT_CLEAR() LXT_SYNCHRONIZATION_POINT_CLEAR_FOR(ChildPid)
#define LXT_SYNCHRONIZATION_POINT_SYNCVARS(_IsChild_, _ParentVar_, _ChildVar_) \
if ((_IsChild_) != FALSE) \
{ \
LxtCheckResult(LxtSynchronizationEventWait(_ChildVar_)); \
LxtCheckResult(LxtSynchronizationEventClear(_ChildVar_)); \
LxtCheckResult(LxtSynchronizationEventSet(_ParentVar_)); \
} \
else \
{ \
LxtCheckResult(LxtSynchronizationEventSet(_ChildVar_)); \
LxtCheckResult(LxtSynchronizationEventWait(_ParentVar_)); \
LxtCheckResult(LxtSynchronizationEventClear(_ParentVar_)); \
}
#define LXT_SYNCHRONIZATION_POINT_CHILD_FOR(_ChildPidVariable_) \
LXT_SYNCHRONIZATION_POINT_SYNCVARS(TRUE, LxtSync##_ChildPidVariable_##Parent, LxtSync##_ChildPidVariable_##Child)
#define LXT_SYNCHRONIZATION_POINT_PARENT_FOR(_ChildPidVariable_) \
LXT_SYNCHRONIZATION_POINT_SYNCVARS(FALSE, LxtSync##_ChildPidVariable_##Parent, LxtSync##_ChildPidVariable_##Child)
#define LXT_SYNCHRONIZATION_POINT_FOR(_ChildPidVariable_) \
if ((_ChildPidVariable_) == 0) \
{ \
LXT_SYNCHRONIZATION_POINT_CHILD_FOR(_ChildPidVariable_); \
} \
else \
{ \
LXT_SYNCHRONIZATION_POINT_PARENT_FOR(_ChildPidVariable_); \
}
#define LXT_SYNCHRONIZATION_POINT_CHILD() LXT_SYNCHRONIZATION_POINT_CHILD_FOR(ChildPid)
#define LXT_SYNCHRONIZATION_POINT_PARENT() LXT_SYNCHRONIZATION_POINT_PARENT_FOR(ChildPid)
#define LXT_SYNCHRONIZATION_POINT() LXT_SYNCHRONIZATION_POINT_FOR(ChildPid);
//
// Declare global synchronization values for common ChildPid variable.
//
LXT_SYNCHRONIZATION_POINT_DECLARE_FOR_STATIC(ChildPid)