queuing_mutex.cpp
Go to the documentation of this file.
/*
Copyright (c) 2005-2020 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "tbb/queuing_mutex.h"
#include "tbb/tbb_machine.h"
#include "tbb/tbb_stddef.h"
#include "tbb_misc.h"
#include "itt_notify.h"
namespace tbb {
using namespace internal;
void queuing_mutex::scoped_lock::acquire( queuing_mutex& m )
{
__TBB_ASSERT( !this->mutex, "scoped_lock is already holding a mutex");
// Must set all fields before the fetch_and_store, because once the
// fetch_and_store executes, *this becomes accessible to other threads.
mutex = &m;
next = NULL;
going = 0;
// The fetch_and_store must have release semantics, because we are
// "sending" the fields initialized above to other processors.
scoped_lock* pred = m.q_tail.fetch_and_store<tbb::release>(this);
if( pred ) {
ITT_NOTIFY(sync_prepare, mutex);
#if TBB_USE_ASSERT
__TBB_control_consistency_helper(); // on "m.q_tail"
__TBB_ASSERT( !pred->next, "the predecessor has another successor!");
#endif
pred->next = this;
spin_wait_while_eq( going, 0ul );
}
ITT_NOTIFY(sync_acquired, mutex);
// Force acquire so that user's critical section receives correct values
// from processor that was previously in the user's critical section.
__TBB_load_with_acquire(going);
}
bool queuing_mutex::scoped_lock::try_acquire( queuing_mutex& m )
{
__TBB_ASSERT( !this->mutex, "scoped_lock is already holding a mutex");
// Must set all fields before the fetch_and_store, because once the
// fetch_and_store executes, *this becomes accessible to other threads.
next = NULL;
going = 0;
// The CAS must have release semantics, because we are
// "sending" the fields initialized above to other processors.
if( m.q_tail.compare_and_swap<tbb::release>(this, NULL) )
return false;
// Force acquire so that user's critical section receives correct values
// from processor that was previously in the user's critical section.
__TBB_load_with_acquire(going);
mutex = &m;
ITT_NOTIFY(sync_acquired, mutex);
return true;
}
void queuing_mutex::scoped_lock::release( )
{
__TBB_ASSERT(this->mutex!=NULL, "no lock acquired");
ITT_NOTIFY(sync_releasing, mutex);
if( !next ) {
if( this == mutex->q_tail.compare_and_swap<tbb::release>(NULL, this) ) {
// this was the only item in the queue, and the queue is now empty.
goto done;
}
// Someone in the queue
spin_wait_while_eq( next, (scoped_lock*)0 );
}
__TBB_ASSERT(next,NULL);
__TBB_store_with_release(next->going, 1);
done:
initialize();
}
void queuing_mutex::internal_construct() {
ITT_SYNC_CREATE(this, _T("tbb::queuing_mutex"), _T(""));
}
} // namespace tbb
__TBB_control_consistency_helper
#define __TBB_control_consistency_helper()
Definition: gcc_generic.h:60
queuing_mutex.h
tbb_machine.h
tbb_stddef.h
__TBB_ASSERT
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:165
itt_notify.h
_T
#define _T(string_literal)
Standard Windows style macro to markup the string literals.
Definition: itt_notify.h:59
ITT_SYNC_CREATE
#define ITT_SYNC_CREATE(obj, type, name)
Definition: itt_notify.h:115
ITT_NOTIFY
#define ITT_NOTIFY(name, obj)
Definition: itt_notify.h:112
tbb_misc.h
sync_releasing
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p sync_releasing
Definition: ittnotify_static.h:104
tbb
The graph class.
Definition: serial/tbb/parallel_for.h:46
tbb::release
@ release
Release.
Definition: atomic.h:59
tbb::internal::__TBB_load_with_acquire
T __TBB_load_with_acquire(const volatile T &location)
Definition: tbb_machine.h:712
tbb::internal::__TBB_store_with_release
void __TBB_store_with_release(volatile T &location, V value)
Definition: tbb_machine.h:716
tbb::internal::spin_wait_while_eq
void spin_wait_while_eq(const volatile T &location, U value)
Spin WHILE the value of the variable is equal to a given value.
Definition: tbb_machine.h:394
internal
Definition: _flow_graph_async_msg_impl.h:24
tbb::queuing_mutex
Queuing mutex with local-only spinning.
Definition: queuing_mutex.h:31
tbb::queuing_mutex::q_tail
atomic< scoped_lock * > q_tail
The last competitor requesting the lock.
Definition: queuing_mutex.h:102
tbb::queuing_mutex::internal_construct
void __TBB_EXPORTED_METHOD internal_construct()
Definition: queuing_mutex.cpp:100
tbb::queuing_mutex::scoped_lock
The scoped locking pattern.
Definition: queuing_mutex.h:44
tbb::queuing_mutex::scoped_lock::release
void __TBB_EXPORTED_METHOD release()
Release lock.
Definition: queuing_mutex.cpp:81
tbb::queuing_mutex::scoped_lock::try_acquire
bool __TBB_EXPORTED_METHOD try_acquire(queuing_mutex &m)
Acquire lock on given mutex if free (i.e. non-blocking)
Definition: queuing_mutex.cpp:58
tbb::queuing_mutex::scoped_lock::next
scoped_lock * next
The pointer to the next competitor for a mutex.
Definition: queuing_mutex.h:84
tbb::queuing_mutex::scoped_lock::acquire
void __TBB_EXPORTED_METHOD acquire(queuing_mutex &m)
Acquire lock on given mutex.
Definition: queuing_mutex.cpp:28

Copyright © 2005-2020 Intel Corporation. All Rights Reserved.

Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are registered trademarks or trademarks of Intel Corporation or its subsidiaries in the United States and other countries.

* Other names and brands may be claimed as the property of others.