Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
libSDL
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
PocketInsanity
libSDL
Commits
b609519a
Commit
b609519a
authored
Jan 26, 2011
by
Sam Lantinga
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added a test to measure the impact of a separate thread periodically locking the queue entirely.
parent
bbc1ba22
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
99 additions
and
26 deletions
+99
-26
testatomic.c
test/testatomic.c
+99
-26
No files found.
test/testatomic.c
View file @
b609519a
...
...
@@ -234,6 +234,11 @@ void RunEpicTest()
/**************************************************************************/
/* Lock-free FIFO test */
/* This is useful to test the impact of another thread locking the queue
entirely for heavy-weight manipulation.
*/
#define TEST_SPINLOCK_FIFO
#define NUM_READERS 4
#define NUM_WRITERS 4
#define EVENTS_PER_WRITER 1000000
...
...
@@ -265,6 +270,14 @@ typedef struct
char
cache_pad3
[
CACHELINE
-
sizeof
(
SDL_atomic_t
)];
#ifdef TEST_SPINLOCK_FIFO
SDL_SpinLock
lock
;
SDL_atomic_t
rwcount
;
SDL_atomic_t
watcher
;
char
cache_pad4
[
CACHELINE
-
sizeof
(
SDL_SpinLock
)
-
2
*
sizeof
(
SDL_atomic_t
)];
#endif
SDL_bool
active
;
/* Only needed for the mutex test */
...
...
@@ -281,6 +294,10 @@ static void InitEventQueue(SDL_EventQueue *queue)
}
SDL_AtomicSet
(
&
queue
->
enqueue_pos
,
0
);
SDL_AtomicSet
(
&
queue
->
dequeue_pos
,
0
);
#ifdef TEST_SPINLOCK_FIFO
queue
->
lock
=
0
;
SDL_AtomicSet
(
&
queue
->
rwcount
,
0
);
#endif
queue
->
active
=
SDL_TRUE
;
}
...
...
@@ -290,6 +307,15 @@ static SDL_bool EnqueueEvent_LockFree(SDL_EventQueue *queue, const SDL_Event *ev
unsigned
queue_pos
;
unsigned
entry_seq
;
int
delta
;
SDL_bool
status
;
#ifdef TEST_SPINLOCK_FIFO
/* This is a gate so an external thread can lock the queue */
SDL_AtomicLock
(
&
queue
->
lock
);
SDL_assert
(
SDL_AtomicGet
(
&
queue
->
watcher
)
==
0
);
SDL_AtomicIncRef
(
&
queue
->
rwcount
);
SDL_AtomicUnlock
(
&
queue
->
lock
);
#endif
queue_pos
=
(
unsigned
)
SDL_AtomicGet
(
&
queue
->
enqueue_pos
);
for
(
;
;
)
{
...
...
@@ -300,22 +326,26 @@ static SDL_bool EnqueueEvent_LockFree(SDL_EventQueue *queue, const SDL_Event *ev
if
(
delta
==
0
)
{
/* The entry and the queue position match, try to increment the queue position */
if
(
SDL_AtomicCAS
(
&
queue
->
enqueue_pos
,
(
int
)
queue_pos
,
(
int
)(
queue_pos
+
1
)))
{
/* We own the object, fill it! */
entry
->
event
=
*
event
;
SDL_AtomicSet
(
&
entry
->
sequence
,
(
int
)(
queue_pos
+
1
));
status
=
SDL_TRUE
;
break
;
}
}
else
if
(
delta
<
0
)
{
/* We ran into an old queue entry, which means it still needs to be dequeued */
return
SDL_FALSE
;
status
=
SDL_FALSE
;
break
;
}
else
{
/* We ran into a new queue entry, get the new queue position */
queue_pos
=
(
unsigned
)
SDL_AtomicGet
(
&
queue
->
enqueue_pos
);
}
}
/* We own the object, fill it! */
entry
->
event
=
*
event
;
SDL_AtomicSet
(
&
entry
->
sequence
,
(
int
)(
queue_pos
+
1
));
return
SDL_TRUE
;
#ifdef TEST_SPINLOCK_FIFO
SDL_AtomicDecRef
(
&
queue
->
rwcount
);
#endif
return
status
;
}
static
SDL_bool
DequeueEvent_LockFree
(
SDL_EventQueue
*
queue
,
SDL_Event
*
event
)
...
...
@@ -324,6 +354,15 @@ static SDL_bool DequeueEvent_LockFree(SDL_EventQueue *queue, SDL_Event *event)
unsigned
queue_pos
;
unsigned
entry_seq
;
int
delta
;
SDL_bool
status
;
#ifdef TEST_SPINLOCK_FIFO
/* This is a gate so an external thread can lock the queue */
SDL_AtomicLock
(
&
queue
->
lock
);
SDL_assert
(
SDL_AtomicGet
(
&
queue
->
watcher
)
==
0
);
SDL_AtomicIncRef
(
&
queue
->
rwcount
);
SDL_AtomicUnlock
(
&
queue
->
lock
);
#endif
queue_pos
=
(
unsigned
)
SDL_AtomicGet
(
&
queue
->
dequeue_pos
);
for
(
;
;
)
{
...
...
@@ -334,22 +373,26 @@ static SDL_bool DequeueEvent_LockFree(SDL_EventQueue *queue, SDL_Event *event)
if
(
delta
==
0
)
{
/* The entry and the queue position match, try to increment the queue position */
if
(
SDL_AtomicCAS
(
&
queue
->
dequeue_pos
,
(
int
)
queue_pos
,
(
int
)(
queue_pos
+
1
)))
{
/* We own the object, fill it! */
*
event
=
entry
->
event
;
SDL_AtomicSet
(
&
entry
->
sequence
,
(
int
)(
queue_pos
+
MAX_ENTRIES
));
status
=
SDL_TRUE
;
break
;
}
}
else
if
(
delta
<
0
)
{
/* We ran into an old queue entry, which means we've hit empty */
return
SDL_FALSE
;
status
=
SDL_FALSE
;
break
;
}
else
{
/* We ran into a new queue entry, get the new queue position */
queue_pos
=
(
unsigned
)
SDL_AtomicGet
(
&
queue
->
dequeue_pos
);
}
}
/* We own the object, fill it! */
*
event
=
entry
->
event
;
SDL_AtomicSet
(
&
entry
->
sequence
,
(
int
)(
queue_pos
+
MAX_ENTRIES
));
return
SDL_TRUE
;
#ifdef TEST_SPINLOCK_FIFO
SDL_AtomicDecRef
(
&
queue
->
rwcount
);
#endif
return
status
;
}
static
SDL_bool
EnqueueEvent_Mutex
(
SDL_EventQueue
*
queue
,
const
SDL_Event
*
event
)
...
...
@@ -358,6 +401,7 @@ static SDL_bool EnqueueEvent_Mutex(SDL_EventQueue *queue, const SDL_Event *event
unsigned
queue_pos
;
unsigned
entry_seq
;
int
delta
;
SDL_bool
status
=
SDL_FALSE
;
SDL_mutexP
(
queue
->
mutex
);
...
...
@@ -368,21 +412,20 @@ static SDL_bool EnqueueEvent_Mutex(SDL_EventQueue *queue, const SDL_Event *event
delta
=
(
int
)(
entry_seq
-
queue_pos
);
if
(
delta
==
0
)
{
++
queue
->
enqueue_pos
.
value
;
/* We own the object, fill it! */
entry
->
event
=
*
event
;
entry
->
sequence
.
value
=
(
int
)(
queue_pos
+
1
);
status
=
SDL_TRUE
;
}
else
if
(
delta
<
0
)
{
/* We ran into an old queue entry, which means it still needs to be dequeued */
SDL_mutexV
(
queue
->
mutex
);
return
SDL_FALSE
;
}
else
{
printf
(
"ERROR: mutex failed!
\n
"
);
}
/* We own the object, fill it! */
entry
->
event
=
*
event
;
entry
->
sequence
.
value
=
(
int
)(
queue_pos
+
1
);
SDL_mutexV
(
queue
->
mutex
);
return
SDL_TRUE
;
return
status
;
}
static
SDL_bool
DequeueEvent_Mutex
(
SDL_EventQueue
*
queue
,
SDL_Event
*
event
)
...
...
@@ -391,6 +434,7 @@ static SDL_bool DequeueEvent_Mutex(SDL_EventQueue *queue, SDL_Event *event)
unsigned
queue_pos
;
unsigned
entry_seq
;
int
delta
;
SDL_bool
status
=
SDL_FALSE
;
SDL_mutexP
(
queue
->
mutex
);
...
...
@@ -401,21 +445,20 @@ static SDL_bool DequeueEvent_Mutex(SDL_EventQueue *queue, SDL_Event *event)
delta
=
(
int
)(
entry_seq
-
(
queue_pos
+
1
));
if
(
delta
==
0
)
{
++
queue
->
dequeue_pos
.
value
;
/* We own the object, fill it! */
*
event
=
entry
->
event
;
entry
->
sequence
.
value
=
(
int
)(
queue_pos
+
MAX_ENTRIES
);
status
=
SDL_TRUE
;
}
else
if
(
delta
<
0
)
{
/* We ran into an old queue entry, which means we've hit empty */
SDL_mutexV
(
queue
->
mutex
);
return
SDL_FALSE
;
}
else
{
printf
(
"ERROR: mutex failed!
\n
"
);
}
/* We own the object, fill it! */
*
event
=
entry
->
event
;
entry
->
sequence
.
value
=
(
int
)(
queue_pos
+
MAX_ENTRIES
);
SDL_mutexV
(
queue
->
mutex
);
return
SDL_TRUE
;
return
status
;
}
static
SDL_sem
*
writersDone
;
...
...
@@ -517,6 +560,29 @@ static int FIFO_Reader(void* _data)
return
0
;
}
#ifdef TEST_SPINLOCK_FIFO
/* This thread periodically locks the queue for no particular reason */
static
int
FIFO_Watcher
(
void
*
_data
)
{
SDL_EventQueue
*
queue
=
(
SDL_EventQueue
*
)
_data
;
while
(
queue
->
active
)
{
SDL_AtomicLock
(
&
queue
->
lock
);
SDL_AtomicIncRef
(
&
queue
->
watcher
);
while
(
SDL_AtomicGet
(
&
queue
->
rwcount
)
>
0
)
{
SDL_Delay
(
0
);
}
/* Do queue manipulation here... */
SDL_AtomicDecRef
(
&
queue
->
watcher
);
SDL_AtomicUnlock
(
&
queue
->
lock
);
/* Wait a bit... */
SDL_Delay
(
1
);
}
return
0
;
}
#endif
/* TEST_SPINLOCK_FIFO */
static
void
RunFIFOTest
(
SDL_bool
lock_free
)
{
SDL_EventQueue
queue
;
...
...
@@ -541,6 +607,13 @@ static void RunFIFOTest(SDL_bool lock_free)
start
=
SDL_GetTicks
();
#ifdef TEST_SPINLOCK_FIFO
/* Start a monitoring thread */
if
(
lock_free
)
{
SDL_CreateThread
(
FIFO_Watcher
,
&
queue
);
}
#endif
/* Start the readers first */
printf
(
"Starting %d readers
\n
"
,
NUM_READERS
);
SDL_zero
(
readerData
);
...
...
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