summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authormidipix <writeonce@midipix.org>2016-08-12 08:49:37 -0400
committermidipix <writeonce@midipix.org>2016-08-12 09:41:49 -0400
commit563a1e17dcddd5b622d07d431a36e74b241993e1 (patch)
tree70d23a9728fe704d622041cb08d7bb151da4d112
parent10e33da88f05b6808532713b0317669a0fdf549a (diff)
downloadntapi-563a1e17dcddd5b622d07d431a36e74b241993e1.tar.bz2
ntapi-563a1e17dcddd5b622d07d431a36e74b241993e1.tar.xz
synchronization block: make all value assignments atomic.
-rw-r--r--include/ntapi/nt_sync.h2
-rw-r--r--src/sync/ntapi_tt_sync_block.c85
2 files changed, 65 insertions, 22 deletions
diff --git a/include/ntapi/nt_sync.h b/include/ntapi/nt_sync.h
index 5b28833..99508dd 100644
--- a/include/ntapi/nt_sync.h
+++ b/include/ntapi/nt_sync.h
@@ -122,7 +122,7 @@ typedef struct _nt_io_completion_basic_information {
typedef union __attr_aligned__(NT_SYNC_BLOCK_SIZE) _nt_sync_block {
- char cache_line[NT_SYNC_BLOCK_SIZE];
+ intptr_t cache_line[NT_SYNC_BLOCK_SIZE/sizeof(intptr_t)];
struct {
int32_t tid;
int32_t pid;
diff --git a/src/sync/ntapi_tt_sync_block.c b/src/sync/ntapi_tt_sync_block.c
index b37659a..0e2a9a4 100644
--- a/src/sync/ntapi_tt_sync_block.c
+++ b/src/sync/ntapi_tt_sync_block.c
@@ -11,6 +11,33 @@
#include <ntapi/ntapi.h>
#include "ntapi_impl.h"
+static void __sync_block_memset(
+ __in nt_sync_block * sync_block,
+ __in intptr_t value)
+{
+ intptr_t * sptr = sync_block->cache_line;
+
+ at_store(&sptr[0x0],value);
+ at_store(&sptr[0x1],value);
+ at_store(&sptr[0x2],value);
+ at_store(&sptr[0x3],value);
+ at_store(&sptr[0x4],value);
+ at_store(&sptr[0x5],value);
+ at_store(&sptr[0x6],value);
+ at_store(&sptr[0x7],value);
+
+ if (sizeof(intptr_t) == 4) {
+ at_store(&sptr[0x8],value);
+ at_store(&sptr[0x9],value);
+ at_store(&sptr[0xa],value);
+ at_store(&sptr[0xb],value);
+ at_store(&sptr[0xc],value);
+ at_store(&sptr[0xd],value);
+ at_store(&sptr[0xe],value);
+ at_store(&sptr[0xf],value);
+ }
+}
+
void __stdcall __ntapi_tt_sync_block_init(
__in nt_sync_block * sync_block,
__in uint32_t flags __optional,
@@ -19,23 +46,32 @@ void __stdcall __ntapi_tt_sync_block_init(
__in int64_t default_lock_wait __optional,
__in void * hsignal __optional)
{
- __ntapi->tt_aligned_block_memset(
- sync_block,
- 0,sizeof(*sync_block));
-
- sync_block->lock_tries = default_lock_tries
- ? default_lock_tries
- : __NT_SYNC_BLOCK_LOCK_TRIES;
-
- sync_block->lock_wait.quad = default_lock_wait
- ? default_lock_wait
- : (-1);
-
- sync_block->flags = flags;
- sync_block->srvtid = srvtid;
- sync_block->hsignal = hsignal;
-
- return;
+ __sync_block_memset(
+ sync_block,0);
+
+ at_store_32(
+ &sync_block->lock_tries,
+ default_lock_tries
+ ? default_lock_tries
+ : __NT_SYNC_BLOCK_LOCK_TRIES);
+
+ at_store_64(
+ &sync_block->lock_wait.quad,
+ default_lock_wait
+ ? default_lock_wait
+ : (-1));
+
+ at_store_32(
+ (int32_t *)&sync_block->flags,
+ flags);
+
+ at_store_32(
+ (int32_t *)&sync_block->srvtid,
+ srvtid);
+
+ at_store(
+ (intptr_t *)&sync_block->hsignal,
+ (intptr_t)hsignal);
}
@@ -148,7 +184,9 @@ int32_t __stdcall __ntapi_tt_sync_block_lock(
if (lock) return NT_STATUS_NOT_LOCKED;
/* shared section support */
- sync_block->pid = pe_get_current_process_id();
+ at_store_32(
+ &sync_block->pid,
+ pe_get_current_process_id());
return NT_STATUS_SUCCESS;
}
@@ -196,7 +234,9 @@ int32_t __stdcall __ntapi_tt_sync_block_server_lock(
}
/* yield request: set */
- sync_block->flags |= NT_SYNC_BLOCK_YIELD_TO_SERVER;
+ at_locked_or_32(
+ (int32_t *)&sync_block->flags,
+ NT_SYNC_BLOCK_YIELD_TO_SERVER);
/* try again */
status = __ntapi_tt_sync_block_lock(
@@ -206,7 +246,9 @@ int32_t __stdcall __ntapi_tt_sync_block_server_lock(
sig_flag);
/* yield request: unset */
- sync_block->flags ^= NT_SYNC_BLOCK_YIELD_TO_SERVER;
+ at_locked_xor_32(
+ (int32_t *)&sync_block->flags,
+ NT_SYNC_BLOCK_YIELD_TO_SERVER);
__ntapi->zw_set_event(
sync_block->hserver,
@@ -281,7 +323,8 @@ int32_t __stdcall __ntapi_tt_sync_block_discard(
if (sync_block->hserver)
__ntapi->zw_close(sync_block->hserver);
- __ntapi->tt_aligned_block_memset(sync_block,-1,sizeof(*sync_block));
+ __sync_block_memset(
+ sync_block,-1);
return NT_STATUS_SUCCESS;
}