dlls/kernelbase/debug.c
static BOOL start_debugger_atomic( EXCEPTION_POINTERS *epointers )
{
    static HANDLE once;

    if (once == 0)
    {
	OBJECT_ATTRIBUTES attr;
	HANDLE event;

	attr.Length                   = sizeof(attr);
	attr.RootDirectory            = 0;
	attr.Attributes               = OBJ_INHERIT;
	attr.ObjectName               = NULL;
	attr.SecurityDescriptor       = NULL;
	attr.SecurityQualityOfService = NULL;

	/* ask for manual reset, so that once the debugger is started,
	 * every thread will know it */
	NtCreateEvent( &event, EVENT_ALL_ACCESS, &attr, NotificationEvent, FALSE );
        if (InterlockedCompareExchangePointer( &once, event, 0 ) == 0)
	{
	    /* ok, our event has been set... we're the winning thread */
	    BOOL ret = start_debugger( epointers, once );

	    if (!ret)
	    {
		/* so that the other threads won't be stuck */
		NtSetEvent( once, NULL );
	    }
	    return ret;
	}

	/* someone beat us here... */
	CloseHandle( event );
    }

    /* and wait for the winner to have actually created the debugger */
    WaitForSingleObject( once, INFINITE );
    /* in fact, here, we only know that someone has tried to start the debugger,
     * we'll know by reposting the exception if it has actually attached
     * to the current process */
    return TRUE;
}
/******************************************************************
 *		start_debugger_atomic
 *
 * starts the debugger in an atomic way:
 *	- either the debugger is not started and it is started
 *	- or the debugger has already been started by another thread
 *	- or the debugger couldn't be started
 *
 * returns TRUE for the two first conditions, FALSE for the last
 */
start_debugger_atomic
starts the debugger in an atomic way:
- either the debugger is not started and it is started
- or the debugger has already been started by another thread
- or the debugger couldn't be started

returns TRUE for the two first conditions, FALSE for the last
start_debugger_atomic starts the debugger in an atomic way : - either the debugger is not started and it is started - or the debugger has already been started by another thread - or the debugger couldn ' t be started returns TRUE for the two first conditions FALSE for the last
static BOOL start_debugger_atomic( EXCEPTION_POINTERS *epointers )
{
    static HANDLE once;
    if (once == 0)
    {
	OBJECT_ATTRIBUTES attr;
	HANDLE event;
	attr.Length                   = sizeof(attr);
	attr.RootDirectory            = 0;
	attr.Attributes               = OBJ_INHERIT;
	attr.ObjectName               = NULL;
	attr.SecurityDescriptor       = NULL;
	attr.SecurityQualityOfService = NULL;
	NtCreateEvent( &event, EVENT_ALL_ACCESS, &attr, NotificationEvent, FALSE );
        if (InterlockedCompareExchangePointer( &once, event, 0 ) == 0)
	{
	    BOOL ret = start_debugger( epointers, once );
	    if (!ret)
	    {
		NtSetEvent( once, NULL );
	    }
	    return ret;
	}
	CloseHandle( event );
    }
    WaitForSingleObject( once, INFINITE );
    return TRUE;
}
static BOOL start_debugger_atomic ( EXCEPTION_POINTERS * epointers ) { static HANDLE once ; if ( once == 0 ) { OBJECT_ATTRIBUTES attr ; HANDLE event ; attr . Length = sizeof ( attr ) ; attr . RootDirectory = 0 ; attr . Attributes = OBJ_INHERIT ; attr . ObjectName = NULL ; attr . SecurityDescriptor = NULL ; attr . SecurityQualityOfService = NULL ; NtCreateEvent ( & event , EVENT_ALL_ACCESS , & attr , NotificationEvent , FALSE ) ; if ( InterlockedCompareExchangePointer ( & once , event , 0 ) == 0 ) { BOOL ret = start_debugger ( epointers , once ) ; if ( ! ret ) { NtSetEvent ( once , NULL ) ; } return ret ; } CloseHandle ( event ) ; } WaitForSingleObject ( once , INFINITE ) ; return TRUE ; }
start_debugger_atomic
 starts the debugger in an atomic way:
      - either the debugger is not started and it is started
      - or the debugger has already been started by another thread
      - or the debugger couldn't be started
start_debugger_atomic starts the debugger in an atomic way : - either the debugger is not started and it is started - or the debugger has already been started by another thread - or the debugger couldn ' t be started
/* ask for manual reset, so that once the debugger is started,
	 * every thread will know it */ /* ok, our event has been set... we're the winning thread */ /* so that the other threads won't be stuck */ /* someone beat us here... */ /* and wait for the winner to have actually created the debugger */ /* in fact, here, we only know that someone has tried to start the debugger,
     * we'll know by reposting the exception if it has actually attached
     * to the current process */