mirror of
https://github.com/microsoft/WSL.git
synced 2025-07-04 07:43:21 +00:00
226 lines
8.5 KiB
C
226 lines
8.5 KiB
C
![]() |
/*++
|
||
|
|
||
|
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)
|