11/*
2- * Copyright (C) 2024 Linux Studio Plugins Project <https://lsp-plug.in/>
3- * (C) 2024 Vladimir Sadovnikov <[email protected] > 2+ * Copyright (C) 2025 Linux Studio Plugins Project <https://lsp-plug.in/>
3+ * (C) 2025 Vladimir Sadovnikov <[email protected] > 44 *
55 * This file is part of lsp-runtime-lib
66 * Created on: 24 апр. 2024 г.
2020 */
2121
2222#include < lsp-plug.in/test-fw/utest.h>
23+ #include < lsp-plug.in/common/atomic.h>
2324#include < lsp-plug.in/ipc/Thread.h>
2425#include < lsp-plug.in/ipc/Mutex.h>
2526#include < lsp-plug.in/ipc/SharedMutex.h>
@@ -34,6 +35,8 @@ UTEST_BEGIN("runtime.ipc", shmutex)
3435 {
3536 ipc::Mutex lock;
3637 LSPString data;
38+ uatomic_t sequence_latch;
39+ size_t errors;
3740
3841 void log (status_t code, const char *event, status_t expected)
3942 {
@@ -42,22 +45,42 @@ UTEST_BEGIN("runtime.ipc", shmutex)
4245
4346 data.append_ascii (event);
4447 data.append (' =' );
45- data.append_ascii ((code == expected) ? " true" : " false" );
48+ if (code == expected)
49+ data.append_ascii (" true" );
50+ else
51+ {
52+ data.fmt_append_ascii (" false(code=%d)" , int (code));
53+ ++errors;
54+ }
4655 data.append (' ;' );
4756 }
4857 } context_t ;
4958
50-
5159 static status_t thread_func1 (void *arg)
5260 {
5361 ipc::SharedMutex mutex;
5462 context_t *ctx = static_cast <context_t *>(arg);
5563
56- ipc::Thread::sleep ( 500 );
64+ wait_latch (ctx-> sequence_latch , 0 );
5765 ctx->log (mutex.open (" test-lsp.lock" ), " open1" , STATUS_OK);
58- ctx->log (mutex.lock (), " SYNC1" , STATUS_OK);
59- ipc::Thread::sleep (800 );
60- ctx->log (mutex.unlock (), " SYNC2" , STATUS_OK);
66+ atomic_add (&ctx->sequence_latch , 1 ); // 0 -> 1
67+
68+ // Sleep 500 ms and lock the mutex
69+ wait_latch (ctx->sequence_latch , 3 );
70+ ipc::Thread::sleep (500 );
71+ ctx->log (mutex.lock (), " SYNC1.lock" , STATUS_OK);
72+ atomic_add (&ctx->sequence_latch , 1 ); // 3 -> 6
73+
74+ // Sleep 200 ms and unlock the mutex
75+ wait_latch (ctx->sequence_latch , 7 );
76+ ipc::Thread::sleep (200 );
77+ ctx->log (mutex.unlock (), " SYNC2.unlock" , STATUS_OK);
78+ atomic_add (&ctx->sequence_latch , 1 ); // 7 -> 9
79+
80+ // Close the mutex
81+ wait_latch (ctx->sequence_latch , 10 );
82+ ctx->log (mutex.close (), " close1" , STATUS_OK);
83+ atomic_add (&ctx->sequence_latch , 1 ); // 10 -> 11
6184
6285 return STATUS_OK;
6386 }
@@ -67,24 +90,47 @@ UTEST_BEGIN("runtime.ipc", shmutex)
6790 ipc::SharedMutex mutex;
6891 context_t *ctx = static_cast <context_t *>(arg);
6992
93+ wait_latch (ctx->sequence_latch , 1 );
7094 ctx->log (mutex.open (" test-lsp.lock" ), " open2" , STATUS_OK);
71- ctx->log (mutex. lock (), " lock2 " , STATUS_OK);
95+ atomic_add (& ctx->sequence_latch , 1 ); // 1 -> 2
7296
97+ // Lock mutex immediately, sleep 500 ms and unlock it
98+ wait_latch (ctx->sequence_latch , 3 );
99+ ctx->log (mutex.lock (), " lock2" , STATUS_OK);
73100 ipc::Thread::sleep (500 );
101+ ctx->log (mutex.unlock (), " SYNC1.unlock" , STATUS_OK);
102+ atomic_add (&ctx->sequence_latch , 1 ); // 3 -> 6
74103
75- ctx->log (mutex.unlock (), " SYNC1" , STATUS_OK);
76-
77- ipc::Thread::sleep (100 );
78-
104+ // Call mutltiple times lock, succeed on last call
105+ wait_latch (ctx->sequence_latch , 6 );
79106 ctx->log (mutex.try_lock (), " trylock2" , STATUS_RETRY);
80107 ctx->log (mutex.lock (500 ), " timedlock2" , STATUS_TIMED_OUT);
81- ctx->log (mutex.lock (500 ), " SYNC2" , STATUS_OK);
108+ atomic_add (&ctx->sequence_latch , 1 ); // 6 -> 7
109+
110+ // Succeed on timed mutex lock
111+ wait_latch (ctx->sequence_latch , 7 );
112+ ctx->log (mutex.lock (800 ), " SYNC2.lock" , STATUS_OK);
113+ atomic_add (&ctx->sequence_latch , 1 ); // 7 -> 9
114+
115+ // Sleep 200 milliseconds and unlock the mutex
116+ wait_latch (ctx->sequence_latch , 9 );
82117 ipc::Thread::sleep (200 );
83- ctx->log (mutex.unlock (), " SYNC3" , STATUS_OK);
118+ ctx->log (mutex.unlock (), " SYNC3.unlock" , STATUS_OK);
119+
120+ // Close the mutex
121+ wait_latch (ctx->sequence_latch , 11 );
122+ ctx->log (mutex.close (), " close2" , STATUS_OK);
123+ atomic_add (&ctx->sequence_latch , 1 ); // 11 -> 12
84124
85125 return STATUS_OK;
86126 }
87127
128+ static void wait_latch (uatomic_t & latch, uatomic_t value)
129+ {
130+ while (atomic_load (&latch) != value)
131+ ipc::Thread::yield ();
132+ }
133+
88134 void test_simple ()
89135 {
90136 ipc::SharedMutex mutex;
@@ -122,6 +168,8 @@ UTEST_BEGIN("runtime.ipc", shmutex)
122168 {
123169 ipc::SharedMutex mutex;
124170 context_t ctx;
171+ atomic_store (&ctx.sequence_latch , uatomic_t (0 ));
172+ ctx.errors = 0 ;
125173
126174 printf (" Testing simple multi-threaded mutex locks\n " );
127175
@@ -134,29 +182,29 @@ UTEST_BEGIN("runtime.ipc", shmutex)
134182 ctx.log (STATUS_OK, " start" , STATUS_OK);
135183 t1.start ();
136184 t2.start ();
185+ wait_latch (ctx.sequence_latch , 2 );
186+ atomic_add (&ctx.sequence_latch , 1 ); // 2 -> 3
137187
188+ // Sleep 200 ms and unlock the mutex
138189 ctx.log (STATUS_OK, " sleep" , STATUS_OK);
139190 ipc::Thread::sleep (200 );
140-
141191 ctx.log (STATUS_OK, " unlock" , STATUS_OK);
142192 UTEST_ASSERT (mutex.unlock () == STATUS_OK);
193+ atomic_add (&ctx.sequence_latch , 1 ); // 3 -> 6
143194
144- ipc::Thread::sleep (2000 );
145- ctx.log (mutex.lock (), " SYNC3" , STATUS_OK);
195+ // Lock the mutex, unlock it and return result
196+ wait_latch (ctx.sequence_latch , 9 );
197+ ctx.log (mutex.lock (), " SYNC3.lock" , STATUS_OK);
146198 ctx.log (mutex.unlock (), " unlock" , STATUS_OK);
147199
148200 ctx.log (mutex.close (), " close" , STATUS_OK);
201+ atomic_add (&ctx.sequence_latch , 1 ); // 9 -> 10
149202
150- static const char *expected =
151- " open=true;lock=true;start=true;sleep=true;open2=true;unlock=true;lock2=true;open1=true;"
152- " SYNC1=true;SYNC1=true;trylock2=true;timedlock2=true;"
153- " SYNC2=true;SYNC2=true;"
154- " SYNC3=true;SYNC3=true;unlock=true;close=true;" ;
155-
156- printf (" Result content: %s\n " , ctx.data .get_ascii ());
157- printf (" Expected content: %s\n " , expected);
203+ // Do final comparison
204+ wait_latch (ctx.sequence_latch , 12 );
158205
159- UTEST_ASSERT (ctx.data .equals_ascii (expected));
206+ printf (" Result sequence: %s\n " , ctx.data .get_ascii ());
207+ UTEST_ASSERT (ctx.errors == 0 );
160208 }
161209
162210 UTEST_MAIN
0 commit comments