diff options
author | midipix <writeonce@midipix.org> | 2016-08-12 08:49:37 -0400 |
---|---|---|
committer | midipix <writeonce@midipix.org> | 2016-08-12 09:41:49 -0400 |
commit | 563a1e17dcddd5b622d07d431a36e74b241993e1 (patch) | |
tree | 70d23a9728fe704d622041cb08d7bb151da4d112 | |
parent | 10e33da88f05b6808532713b0317669a0fdf549a (diff) | |
download | ntapi-563a1e17dcddd5b622d07d431a36e74b241993e1.tar.bz2 ntapi-563a1e17dcddd5b622d07d431a36e74b241993e1.tar.xz |
synchronization block: make all value assignments atomic.
-rw-r--r-- | include/ntapi/nt_sync.h | 2 | ||||
-rw-r--r-- | src/sync/ntapi_tt_sync_block.c | 85 |
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; } |