Code can not be changed(NtProtectVM ret. STATUS_SECTION_PROTECTION).
Code:
.data
pGdiGetSpoolMessage	PVOID ?
RegionAddress	PVOID 0
SynchLock		BOOLEAN FALSE
RaiseLock		BOOLEAN FALSE
.code
ThreadStartupRoutine proc UserParameter:PVOID
WaitLock:
	cmp SynchLock,FALSE
	je WaitLock
	mov RaiseLock,FALSE
; Align 4, W.
	push 0
	push 0
	push PAGE_SIZE
	push RegionAddress
	Call pGdiGetSpoolMessage
	mov RaiseLock,TRUE
	jmp WaitLock
ThreadStartupRoutine endp
%PERR macro
	.if Eax != STATUS_INVALID_PAGE_PROTECTION
		int 3
	.endif
endm
%APIERR macro
	.if !Eax
		int 3
	.endif
endm
$Gdi32	CHAR "Gdi32.dll",0
$Entry	CHAR "GdiGetSpoolMessage",0
Entry proc
Local ClientId:CLIENT_ID
Local ThreadHandle:HANDLE
Local RegionSize:ULONG
Local OldProtect:ULONG
Local DllHandle:PVOID
	invoke LoadLibrary, addr $Gdi32
	%APIERR
	invoke GetProcAddress, Eax, offset $Entry
	%APIERR
	mov pGdiGetSpoolMessage,eax
	invoke RtlCreateUserThread, NtCurrentProcess, NULL, FALSE, 0, 0, 0, addr ThreadStartupRoutine, 0, addr ThreadHandle, addr ClientId
Synch:
	mov RegionSize,PAGE_SIZE
	mov RegionAddress,0
	invoke ZwAllocateVirtualMemory, NtCurrentProcess, addr RegionAddress, 0, addr RegionSize, MEM_COMMIT, PAGE_READWRITE
	mov SynchLock,TRUE
	invoke ZwSuspendThread, ThreadHandle, NULL
	invoke ZwFreeVirtualMemory, NtCurrentProcess, addr RegionAddress, addr RegionSize, MEM_RELEASE
	test eax,eax
	mov SynchLock,FALSE
	jnz Raise
	invoke ZwResumeThread, ThreadHandle, NULL
	jmp Synch
Raise:
	%PERR
; test for free.
	invoke ZwFreeVirtualMemory, NtCurrentProcess, addr RegionAddress, addr RegionSize, MEM_RELEASE
	%PERR
; test for change.
	invoke ZwProtectVirtualMemory, NtCurrentProcess, addr RegionAddress, addr RegionSize, PAGE_NOACCESS, addr OldProtect
	%PERR
; Unlock
	invoke ZwResumeThread, ThreadHandle, NULL
@@:
	cmp RaiseLock,FALSE
	je @b
	invoke ZwFreeVirtualMemory, NtCurrentProcess, addr RegionAddress, addr RegionSize, MEM_RELEASE
	int 3
	ret
Entry endp
 
Guard does not work for the region, which is described in TEB(StackBase & StackLimit).