mirror of
https://github.com/microsoft/WSL.git
synced 2025-07-03 15:23:22 +00:00

Many Microsoft employees have contributed to the Windows Subsystem for Linux, this commit is the result of their work since 2016. The entire history of the Windows Subsystem for Linux can't be shared here, but here's an overview of WSL's history after it moved to it own repository in 2021: Number of commits on the main branch: 2930 Number of contributors: 31 Head over https://github.com/microsoft/WSL/releases for a more detailed history of the features added to WSL since 2021.
226 lines
No EOL
8.5 KiB
C
226 lines
No EOL
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) |