Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
FORMUS3IC_LAS3
/
embb
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
46adb817
authored
9 years ago
by
Christian Kern
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Worked in review comments for ticket EMBB453
parent
e62df23a
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
366 additions
and
27 deletions
+366
-27
base_c/include/embb/base/c/mutex.h
+1
-1
base_c/src/mutex.c
+118
-0
base_c/test/shared_mutex_test.cc
+117
-2
base_c/test/shared_mutex_test.h
+8
-0
base_cpp/src/mutex.cc
+122
-14
base_cpp/test/shared_mutex_test.cc
+0
-10
No files found.
base_c/include/embb/base/c/mutex.h
View file @
46adb817
...
...
@@ -314,4 +314,4 @@ void embb_shared_mutex_destroy(
* \}
*/
#endif
/* EMBB_BASE_C_MUTEX_H_ */
#endif
// EMBB_BASE_C_MUTEX_H_
This diff is collapsed.
Click to expand it.
base_c/src/mutex.c
View file @
46adb817
...
...
@@ -115,3 +115,121 @@ void embb_mutex_destroy(embb_mutex_t* mutex) {
}
#endif
/* EMBB_PLATFORM_THREADING_POSIXTHREADS */
#ifdef EMBB_PLATFORM_THREADING_WINTHREADS
int
embb_shared_mutex_init
(
embb_shared_mutex_t
*
shared_mutex
)
{
InitializeSRWLock
(
shared_mutex
);
return
EMBB_SUCCESS
;
}
int
embb_shared_mutex_lock
(
embb_shared_mutex_t
*
shared_mutex
)
{
AcquireSRWLockExclusive
(
shared_mutex
);
return
EMBB_SUCCESS
;
}
int
embb_shared_mutex_try_lock
(
embb_shared_mutex_t
*
shared_mutex
)
{
BOOLEAN
success
;
success
=
TryAcquireSRWLockExclusive
(
shared_mutex
);
if
(
success
==
0
)
return
EMBB_BUSY
;
return
EMBB_SUCCESS
;
}
int
embb_shared_mutex_unlock
(
embb_shared_mutex_t
*
shared_mutex
)
{
ReleaseSRWLockExclusive
(
shared_mutex
);
return
EMBB_SUCCESS
;
}
int
embb_shared_mutex_lock_shared
(
embb_shared_mutex_t
*
shared_mutex
)
{
AcquireSRWLockShared
(
shared_mutex
);
return
EMBB_SUCCESS
;
}
int
embb_shared_mutex_try_lock_shared
(
embb_shared_mutex_t
*
shared_mutex
)
{
BOOLEAN
success
;
success
=
TryAcquireSRWLockShared
(
shared_mutex
);
if
(
success
==
0
)
return
EMBB_BUSY
;
return
EMBB_SUCCESS
;
}
int
embb_shared_mutex_unlock_shared
(
embb_shared_mutex_t
*
shared_mutex
)
{
ReleaseSRWLockShared
(
shared_mutex
);
return
EMBB_SUCCESS
;
}
void
embb_shared_mutex_destroy
(
embb_shared_mutex_t
*
shared_mutex
)
{
// Quoting MSDN: "SRW locks do not need to be explicitly destroyed".
EMBB_UNUSED
(
shared_mutex
);
}
#endif
/* EMBB_PLATFORM_THREADING_WINTHREADS */
#ifdef EMBB_PLATFORM_THREADING_POSIXTHREADS
int
embb_shared_mutex_init
(
embb_shared_mutex_t
*
shared_mutex
)
{
int
result
=
pthread_rwlock_init
(
shared_mutex
,
NULL
);
if
(
result
!=
0
)
{
return
EMBB_ERROR
;
}
return
EMBB_SUCCESS
;
}
int
embb_shared_mutex_lock
(
embb_shared_mutex_t
*
shared_mutex
)
{
int
result
=
pthread_rwlock_wrlock
(
shared_mutex
);
if
(
result
!=
0
)
{
return
EMBB_ERROR
;
}
return
EMBB_SUCCESS
;
}
int
embb_shared_mutex_try_lock
(
embb_shared_mutex_t
*
shared_mutex
)
{
int
result
=
pthread_rwlock_trywrlock
(
shared_mutex
);
if
(
result
==
0
)
{
return
EMBB_SUCCESS
;
}
if
(
result
==
EBUSY
)
{
return
EMBB_BUSY
;
}
return
EMBB_ERROR
;
}
int
embb_shared_mutex_unlock
(
embb_shared_mutex_t
*
shared_mutex
)
{
int
result
=
pthread_rwlock_unlock
(
shared_mutex
);
if
(
result
!=
0
)
{
return
EMBB_ERROR
;
}
return
EMBB_SUCCESS
;
}
int
embb_shared_mutex_lock_shared
(
embb_shared_mutex_t
*
shared_mutex
)
{
int
result
=
pthread_rwlock_rdlock
(
shared_mutex
);
if
(
result
!=
0
)
{
return
EMBB_ERROR
;
}
return
EMBB_SUCCESS
;
}
int
embb_shared_mutex_try_lock_shared
(
embb_shared_mutex_t
*
shared_mutex
)
{
int
result
=
pthread_rwlock_tryrdlock
(
shared_mutex
);
if
(
result
==
0
)
{
return
EMBB_SUCCESS
;
}
if
(
result
==
EBUSY
)
{
return
EMBB_BUSY
;
}
return
EMBB_ERROR
;
}
int
embb_shared_mutex_unlock_shared
(
embb_shared_mutex_t
*
shared_mutex
)
{
int
result
=
pthread_rwlock_unlock
(
shared_mutex
);
if
(
result
!=
0
)
{
return
EMBB_ERROR
;
}
return
EMBB_SUCCESS
;
}
void
embb_shared_mutex_destroy
(
embb_shared_mutex_t
*
shared_mutex
)
{
pthread_rwlock_destroy
(
shared_mutex
);
}
#endif
/* EMBB_PLATFORM_THREADING_POSIXTHREADS */
This diff is collapsed.
Click to expand it.
base_c/test/shared_mutex_test.cc
View file @
46adb817
...
...
@@ -30,7 +30,6 @@
namespace
embb
{
namespace
base
{
namespace
test
{
SharedMutexTest
::
SharedMutexTest
()
:
shared_mutex_
(),
counter_
(
0
),
...
...
@@ -48,6 +47,123 @@ SharedMutexTest::SharedMutexTest()
.
Add
(
&
SharedMutexTest
::
TestExclusiveWriterWriterMethod
,
this
,
num_threads_
/
2
,
num_iterations_
)
.
Post
(
&
SharedMutexTest
::
TestExclusiveWriterPost
,
this
);
CreateUnit
(
"Basic test: read lock after write lock fails"
)
.
Pre
(
&
SharedMutexTest
::
TestLockedPre
,
this
)
.
Add
(
&
SharedMutexTest
::
TestLockedForWritingPreventsLockForReading
,
this
,
2
,
num_iterations_
)
.
Add
(
&
SharedMutexTest
::
TestLockedPost
,
this
);
CreateUnit
(
"Basic test: write lock after read lock fails"
)
.
Pre
(
&
SharedMutexTest
::
TestLockedPre
,
this
)
.
Add
(
&
SharedMutexTest
::
TestLockedForReadingPreventsLockForWriting
,
this
,
2
,
num_iterations_
)
.
Add
(
&
SharedMutexTest
::
TestLockedPost
,
this
);
}
void
SharedMutexTest
::
TestLockedPre
()
{
embb_atomic_store_int
(
&
synchronize_
,
0
);
int
success
=
embb_shared_mutex_init
(
&
shared_mutex_
);
PT_ASSERT_EQ_MSG
(
success
,
EMBB_SUCCESS
,
"Failed to initialize shared mutex."
);
}
void
SharedMutexTest
::
TestLockedForWritingPreventsLockForReading
()
{
int
expected
=
0
;
int
success
=
0
;
int
which_thread
=
0
;
if
(
embb_atomic_compare_and_swap_int
(
&
synchronize_
,
&
expected
,
1
))
{
// we are the write locking thread (will happen first)!
success
=
embb_shared_mutex_lock
(
&
shared_mutex_
);
PT_ASSERT_EQ_MSG
(
success
,
EMBB_SUCCESS
,
"Failed to lock shared mutex for writing"
);
// signal the second thread to continue
embb_atomic_store_int
(
&
synchronize_
,
2
);
}
else
{
while
(
embb_atomic_load_int
(
&
synchronize_
)
!=
2
)
{}
// we are the read lock thread! (second thread)
which_thread
=
1
;
// the mutex is locked for writing... try lock for reading must fail now!
success
=
embb_shared_mutex_try_lock_shared
(
&
shared_mutex_
);
PT_ASSERT_EQ_MSG
(
success
,
EMBB_BUSY
,
"Not failed to lock shared mutex for reading"
);
// synchronize, that first thread can unlock
embb_atomic_store_int
(
&
synchronize_
,
3
);
}
if
(
which_thread
==
0
)
{
// wait for second thread to finish!
while
(
embb_atomic_load_int
(
&
synchronize_
)
!=
3
)
{}
// the first thread unlocks the mutex...
success
=
embb_shared_mutex_unlock
(
&
shared_mutex_
);
PT_ASSERT_EQ_MSG
(
success
,
EMBB_SUCCESS
,
"Failed to unlock mutex"
);
// reset synchronize flag for next round...
embb_atomic_store_int
(
&
synchronize_
,
0
);
}
else
{
//wait for next round
while
(
embb_atomic_load_int
(
&
synchronize_
)
==
3
)
{}
}
}
void
SharedMutexTest
::
TestLockedForReadingPreventsLockForWriting
()
{
int
expected
=
0
;
int
success
=
0
;
int
which_thread
=
0
;
if
(
embb_atomic_compare_and_swap_int
(
&
synchronize_
,
&
expected
,
1
))
{
// we are the write locking thread (will happen first)!
success
=
embb_shared_mutex_lock_shared
(
&
shared_mutex_
);
PT_ASSERT_EQ_MSG
(
success
,
EMBB_SUCCESS
,
"Failed to lock shared mutex for writing"
);
// signal the second thread to continue
embb_atomic_store_int
(
&
synchronize_
,
2
);
}
else
{
while
(
embb_atomic_load_int
(
&
synchronize_
)
!=
2
)
{}
// we are the read lock thread! (second thread)
which_thread
=
1
;
// the mutex is locked for writing... try lock for reading must fail now!
success
=
embb_shared_mutex_try_lock
(
&
shared_mutex_
);
PT_ASSERT_EQ_MSG
(
success
,
EMBB_BUSY
,
"Not failed to lock shared mutex for reading"
);
// synchronize, that first thread can unlock
embb_atomic_store_int
(
&
synchronize_
,
3
);
}
if
(
which_thread
==
0
)
{
// wait for second thread to finish!
while
(
embb_atomic_load_int
(
&
synchronize_
)
!=
3
)
{}
// the first thread unlocks the mutex...
success
=
embb_shared_mutex_unlock
(
&
shared_mutex_
);
PT_ASSERT_EQ_MSG
(
success
,
EMBB_SUCCESS
,
"Failed to unlock mutex"
);
// reset synchronize flag for next round...
embb_atomic_store_int
(
&
synchronize_
,
0
);
}
else
{
//wait for next round
while
(
embb_atomic_load_int
(
&
synchronize_
)
==
3
)
{}
}
}
void
SharedMutexTest
::
TestLockedPost
()
{
embb_shared_mutex_destroy
(
&
shared_mutex_
);
}
void
SharedMutexTest
::
TestSharedReadPre
()
{
...
...
@@ -105,7 +221,6 @@ void SharedMutexTest::TestExclusiveWriterPost() {
"Counter value is inconsistent."
);
embb_shared_mutex_destroy
(
&
shared_mutex_
);
}
}
// namespace test
}
// namespace base
}
// namespace embb
This diff is collapsed.
Click to expand it.
base_c/test/shared_mutex_test.h
View file @
46adb817
...
...
@@ -30,6 +30,7 @@
#include <partest/partest.h>
#include <embb/base/c/internal/platform.h>
#include <embb/base/c/mutex.h>
#include <embb/base/c/atomic.h>
namespace
embb
{
...
...
@@ -63,6 +64,13 @@ class SharedMutexTest : public partest::TestCase {
void
TestExclusiveWriterWriterMethod
();
void
TestExclusiveWriterPost
();
void
TestLockedForWritingPreventsLockForReading
();
void
TestLockedForReadingPreventsLockForWriting
();
void
TestLockedPost
();
void
TestLockedPre
();
embb_atomic_int
synchronize_
;
embb_shared_mutex_t
shared_mutex_
;
size_t
counter_
;
size_t
num_threads_
;
...
...
This diff is collapsed.
Click to expand it.
base_cpp/src/mutex.cc
View file @
46adb817
...
...
@@ -30,28 +30,26 @@
namespace
embb
{
namespace
base
{
namespace
internal
{
MutexBase
::
MutexBase
(
int
mutex_type
)
:
mutex_
()
{
MutexBase
::
MutexBase
(
int
mutex_type
)
:
mutex_
()
{
embb_mutex_init
(
&
mutex_
,
mutex_type
);
}
}
MutexBase
::~
MutexBase
()
{
MutexBase
::~
MutexBase
()
{
embb_mutex_destroy
(
&
mutex_
);
}
}
void
MutexBase
::
Lock
()
{
void
MutexBase
::
Lock
()
{
embb_mutex_lock
(
&
mutex_
);
}
}
bool
MutexBase
::
TryLock
()
{
bool
MutexBase
::
TryLock
()
{
int
result
=
embb_mutex_try_lock
(
&
mutex_
);
return
result
==
EMBB_SUCCESS
;
}
}
void
MutexBase
::
Unlock
()
{
void
MutexBase
::
Unlock
()
{
embb_mutex_unlock
(
&
mutex_
);
}
}
}
// namespace internal
Mutex
::
Mutex
()
:
MutexBase
(
EMBB_MUTEX_PLAIN
)
{
...
...
@@ -60,8 +58,118 @@ Mutex::Mutex() : MutexBase(EMBB_MUTEX_PLAIN) {
RecursiveMutex
::
RecursiveMutex
()
:
MutexBase
(
EMBB_MUTEX_RECURSIVE
)
{
}
}
// namespace base
}
// namespace embb
SharedMutex
::
SharedMutex
()
:
shared_mutex_
()
{
int
result
=
embb_shared_mutex_init
(
&
shared_mutex_
);
switch
(
result
)
{
case
EMBB_SUCCESS
:
return
;
case
EMBB_ERROR
:
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Error while initializing mutex."
);
break
;
default
:
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Unknown error."
);
break
;
}
}
SharedMutex
::~
SharedMutex
()
{
embb_shared_mutex_destroy
(
&
shared_mutex_
);
}
void
SharedMutex
::
Lock
()
{
int
result
=
embb_shared_mutex_lock
(
&
shared_mutex_
);
switch
(
result
)
{
case
EMBB_SUCCESS
:
return
;
case
EMBB_ERROR
:
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Error while acquiring mutex."
);
break
;
default
:
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Unknown error."
);
break
;
}
}
bool
SharedMutex
::
TryLock
()
{
int
result
=
embb_shared_mutex_try_lock
(
&
shared_mutex_
);
switch
(
result
)
{
case
EMBB_SUCCESS
:
return
true
;
case
EMBB_BUSY
:
return
false
;
case
EMBB_ERROR
:
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Error while acquiring mutex."
);
break
;
default
:
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Unknown error."
);
break
;
}
}
void
SharedMutex
::
Unlock
()
{
int
result
=
embb_shared_mutex_unlock
(
&
shared_mutex_
);
switch
(
result
)
{
case
EMBB_SUCCESS
:
return
;
case
EMBB_ERROR
:
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Error while releasing mutex."
);
break
;
default
:
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Unknown error."
);
break
;
}
}
void
SharedMutex
::
LockShared
()
{
int
result
=
embb_shared_mutex_lock_shared
(
&
shared_mutex_
);
switch
(
result
)
{
case
EMBB_SUCCESS
:
return
;
case
EMBB_ERROR
:
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Error while acquiring mutex."
);
break
;
default
:
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Unknown error."
);
break
;
}
}
bool
SharedMutex
::
TryLockShared
()
{
int
result
=
embb_shared_mutex_try_lock_shared
(
&
shared_mutex_
);
switch
(
result
)
{
case
EMBB_SUCCESS
:
return
true
;
case
EMBB_BUSY
:
return
false
;
case
EMBB_ERROR
:
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Error while acquiring mutex."
);
break
;
default
:
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Unknown error."
);
break
;
}
}
void
SharedMutex
::
UnlockShared
()
{
int
result
=
embb_shared_mutex_unlock_shared
(
&
shared_mutex_
);
switch
(
result
)
{
case
EMBB_SUCCESS
:
return
;
case
EMBB_ERROR
:
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Error while releasing mutex."
);
break
;
default
:
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Unknown error."
);
break
;
}
}
}
// namespace base
}
// namespace embb
This diff is collapsed.
Click to expand it.
base_cpp/test/shared_mutex_test.cc
View file @
46adb817
...
...
@@ -31,7 +31,6 @@
namespace
embb
{
namespace
base
{
namespace
test
{
SharedMutexTest
::
SharedMutexTest
()
:
shared_mutex_
(),
counter_
(
0
),
...
...
@@ -55,9 +54,6 @@ SharedMutexTest::SharedMutexTest()
void
SharedMutexTest
::
TestSharedReadThreadMethod
()
{
SharedLock
<
embb
::
base
::
SharedMutex
>
lock
(
shared_mutex_
,
embb
::
base
::
try_lock
);
PT_ASSERT_EQ_MSG
(
lock
.
OwnsLock
(),
true
,
"Failed to lock for reading."
);
int
spin
=
10000
;
while
(
--
spin
!=
0
);
}
void
SharedMutexTest
::
TestExclusiveWritePre
()
{
...
...
@@ -67,11 +63,6 @@ void SharedMutexTest::TestExclusiveWritePre() {
void
SharedMutexTest
::
TestExclusiveWriteReaderMethod
()
{
// Just add some contention
SharedLock
<
embb
::
base
::
SharedMutex
>
lock
(
shared_mutex_
,
embb
::
base
::
try_lock
);
if
(
lock
.
OwnsLock
())
{
int
spin
=
10000
;
while
(
--
spin
!=
0
);
}
}
void
SharedMutexTest
::
TestExclusiveWriteWriterMethod
()
{
...
...
@@ -152,7 +143,6 @@ void SharedMutexTest::TestSharedLockThreadMethod() {
PT_EXPECT_EQ
(
lock1
.
OwnsLock
(),
false
);
}
}
}
// namespace test
}
// namespace base
}
// namespace embb
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment