|  | @@ -254,6 +254,7 @@ static void memfault_upcall (PAL_PTR event, PAL_NUM arg, PAL_CONTEXT * context)
 | 
	
		
			
				|  |  |          && (void *) arg >= tcb->test_range.start
 | 
	
		
			
				|  |  |          && (void *) arg <= tcb->test_range.end) {
 | 
	
		
			
				|  |  |          assert(context);
 | 
	
		
			
				|  |  | +        tcb->test_range.has_fault = true;
 | 
	
		
			
				|  |  |          context->rip = (PAL_NUM) tcb->test_range.cont_addr;
 | 
	
		
			
				|  |  |          goto ret_exception;
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -365,14 +366,15 @@ bool test_user_memory (void * addr, size_t size, bool write)
 | 
	
		
			
				|  |  |      assert(tcb && tcb->tp);
 | 
	
		
			
				|  |  |      __disable_preempt(tcb);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    bool  has_fault = true;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      /* Add the memory region to the watch list. This is not racy because
 | 
	
		
			
				|  |  |       * each thread has its own record. */
 | 
	
		
			
				|  |  |      assert(!tcb->test_range.cont_addr);
 | 
	
		
			
				|  |  | +    tcb->test_range.has_fault = false;
 | 
	
		
			
				|  |  |      tcb->test_range.cont_addr = &&ret_fault;
 | 
	
		
			
				|  |  |      tcb->test_range.start = addr;
 | 
	
		
			
				|  |  |      tcb->test_range.end   = addr + size - 1;
 | 
	
		
			
				|  |  | +    /* enforce compiler to store tcb->test_range into memory */
 | 
	
		
			
				|  |  | +    __asm__ volatile(""::: "memory");
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /* Try to read or write into one byte inside each page */
 | 
	
		
			
				|  |  |      void * tmp = addr;
 | 
	
	
		
			
				|  | @@ -385,11 +387,14 @@ bool test_user_memory (void * addr, size_t size, bool write)
 | 
	
		
			
				|  |  |          tmp = ALIGN_UP(tmp + 1);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    has_fault = false; /* All accesses have passed. Nothing wrong. */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  ret_fault:
 | 
	
		
			
				|  |  | +    /* enforce compiler to load tcb->test_range.has_fault below */
 | 
	
		
			
				|  |  | +    __asm__ volatile("": "=m"(tcb->test_range.has_fault));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      /* If any read or write into the target region causes an exception,
 | 
	
		
			
				|  |  |       * the control flow will immediately jump to here. */
 | 
	
		
			
				|  |  | +    bool has_fault = tcb->test_range.has_fault;
 | 
	
		
			
				|  |  | +    tcb->test_range.has_fault = false;
 | 
	
		
			
				|  |  |      tcb->test_range.cont_addr = NULL;
 | 
	
		
			
				|  |  |      tcb->test_range.start = tcb->test_range.end = NULL;
 | 
	
		
			
				|  |  |      __enable_preempt(tcb);
 | 
	
	
		
			
				|  | @@ -432,10 +437,11 @@ bool test_user_string (const char * addr)
 | 
	
		
			
				|  |  |      assert(tcb && tcb->tp);
 | 
	
		
			
				|  |  |      __disable_preempt(tcb);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    bool has_fault = true;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      assert(!tcb->test_range.cont_addr);
 | 
	
		
			
				|  |  | +    tcb->test_range.has_fault = false;
 | 
	
		
			
				|  |  |      tcb->test_range.cont_addr = &&ret_fault;
 | 
	
		
			
				|  |  | +    /* enforce compiler to store tcb->test_range into memory */
 | 
	
		
			
				|  |  | +    __asm__ volatile(""::: "memory");
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      do {
 | 
	
		
			
				|  |  |          /* Add the memory region to the watch list. This is not racy because
 | 
	
	
		
			
				|  | @@ -454,11 +460,14 @@ bool test_user_string (const char * addr)
 | 
	
		
			
				|  |  |          next = ALIGN_UP(addr + 1);
 | 
	
		
			
				|  |  |      } while (size == maxlen);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    has_fault = false; /* All accesses have passed. Nothing wrong. */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  ret_fault:
 | 
	
		
			
				|  |  | +    /* enforce compiler to load tcb->test_range.has_fault below */
 | 
	
		
			
				|  |  | +    __asm__ volatile("": "=m"(tcb->test_range.has_fault));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      /* If any read or write into the target region causes an exception,
 | 
	
		
			
				|  |  |       * the control flow will immediately jump to here. */
 | 
	
		
			
				|  |  | +    bool has_fault = tcb->test_range.has_fault;
 | 
	
		
			
				|  |  | +    tcb->test_range.has_fault = false;
 | 
	
		
			
				|  |  |      tcb->test_range.cont_addr = NULL;
 | 
	
		
			
				|  |  |      tcb->test_range.start = tcb->test_range.end = NULL;
 | 
	
		
			
				|  |  |      __enable_preempt(tcb);
 |