tests: Impl pthread tests: detach, exit, mutex
Signed-off-by: Max Logaev <maxlogaev@proton.me>
This commit is contained in:
@@ -5,7 +5,10 @@ project(tests C)
|
||||
add_executable(hello hello.c)
|
||||
add_executable(malloc malloc.c)
|
||||
|
||||
add_executable(pthread_create pthread.c)
|
||||
target_link_options(malloc PRIVATE -Wl,-Map=malloc.map)
|
||||
add_executable(detach pthread/detach.c)
|
||||
add_executable(create pthread/create.c)
|
||||
add_executable(exit pthread/exit.c)
|
||||
add_executable(mutex pthread/mutex.c)
|
||||
|
||||
install(TARGETS hello malloc pthread_create DESTINATION tests)
|
||||
install(TARGETS hello malloc DESTINATION tests)
|
||||
install(TARGETS mutex create detach exit DESTINATION tests/pthread)
|
||||
|
||||
@@ -45,7 +45,6 @@ main ()
|
||||
// free()
|
||||
for (size_t i = 0; i < MAX_ALLOCS; i++)
|
||||
{
|
||||
__kos_dbg_printf ("%u ", i);
|
||||
free (allocs[i]);
|
||||
}
|
||||
|
||||
|
||||
78
tests/pthread/detach.c
Normal file
78
tests/pthread/detach.c
Normal file
@@ -0,0 +1,78 @@
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <kolibrios/dbg.h>
|
||||
#include <kolibrios/syscall.h>
|
||||
|
||||
void *
|
||||
thread_sleep (void *arg)
|
||||
{
|
||||
_ksys (SF_SLEEP, 500); // sleep 5 sec
|
||||
__kos_dbg_puts ("I: thread_sleep: exit!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *
|
||||
thread_no_sleep (void *arg)
|
||||
{
|
||||
__kos_dbg_puts ("I: thread_no_sleep: exit!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
int rc = 0;
|
||||
pthread_t id1, id2;
|
||||
|
||||
rc = pthread_create (&id1, NULL, thread_sleep, NULL);
|
||||
if (rc)
|
||||
{
|
||||
__kos_dbg_printf ("E: pthread_create() failed: %s\n", strerror (rc));
|
||||
return 1;
|
||||
}
|
||||
|
||||
__kos_dbg_puts ("I: Created thread_sleep");
|
||||
|
||||
rc = pthread_create (&id2, NULL, thread_no_sleep, NULL);
|
||||
if (rc)
|
||||
{
|
||||
__kos_dbg_printf ("E: pthread_create() failed: %s\n", strerror (rc));
|
||||
return 1;
|
||||
}
|
||||
|
||||
__kos_dbg_puts ("I: Created thread_no_sleep");
|
||||
|
||||
rc = pthread_detach (id1);
|
||||
if (rc)
|
||||
{
|
||||
__kos_dbg_printf ("E: pthread_detach() failed: %s\n", strerror (rc));
|
||||
return 1;
|
||||
}
|
||||
|
||||
rc = pthread_detach (id2);
|
||||
if (rc)
|
||||
{
|
||||
__kos_dbg_printf ("E: pthread_detach() failed: %s\n", strerror (rc));
|
||||
return 1;
|
||||
}
|
||||
|
||||
rc = pthread_join (id1, NULL);
|
||||
if (!rc)
|
||||
{
|
||||
__kos_dbg_puts ("E: 'thread_sleep' joined");
|
||||
return 1;
|
||||
}
|
||||
|
||||
_ksys (SF_SLEEP, 500); // sleep 5s
|
||||
|
||||
rc = pthread_join (id2, NULL);
|
||||
if (!rc)
|
||||
{
|
||||
__kos_dbg_puts ("E: 'thread_no_sleep' joined");
|
||||
return 1;
|
||||
}
|
||||
|
||||
__kos_dbg_puts ("I: Detach test: OK!");
|
||||
return 0;
|
||||
}
|
||||
79
tests/pthread/exit.c
Normal file
79
tests/pthread/exit.c
Normal file
@@ -0,0 +1,79 @@
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdlib.h>
|
||||
#include <kolibrios/syscall.h>
|
||||
|
||||
static atomic_int count;
|
||||
static pthread_spinlock_t spin;
|
||||
|
||||
static void *
|
||||
thread (void *arg)
|
||||
{
|
||||
_ksys (SF_SLEEP, 50);
|
||||
|
||||
int c = 0;
|
||||
pthread_spin_lock (&spin);
|
||||
|
||||
if (count >= 100)
|
||||
{
|
||||
__kos_dbg_puts (
|
||||
"I: Test end. Please make sure all threads are terminated.");
|
||||
pthread_spin_unlock (&spin);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
c = count;
|
||||
count++;
|
||||
|
||||
pthread_spin_unlock (&spin);
|
||||
|
||||
pthread_t id;
|
||||
int rc = pthread_create (&id, NULL, thread, NULL);
|
||||
if (rc)
|
||||
{
|
||||
__kos_dbg_printf ("E: %d pthread_create() failed: %s\n", c,
|
||||
strerror (rc));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = pthread_detach (id);
|
||||
if (rc)
|
||||
{
|
||||
__kos_dbg_printf ("E: pthread_detach() failed: %s\n", strerror (rc));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
_ksys (SF_SLEEP, 100);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
pthread_t id;
|
||||
int rc = pthread_create (&id, NULL, thread, NULL);
|
||||
if (rc)
|
||||
{
|
||||
__kos_dbg_printf ("E: pthread_create() failed: %s\n", strerror (rc));
|
||||
return 1;
|
||||
}
|
||||
|
||||
rc = pthread_detach (id);
|
||||
if (rc)
|
||||
{
|
||||
__kos_dbg_printf ("E: pthread_detach() failed: %s\n", strerror (rc));
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
_ksys (SF_SLEEP, 100);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
89
tests/pthread/mutex.c
Normal file
89
tests/pthread/mutex.c
Normal file
@@ -0,0 +1,89 @@
|
||||
#include <pthread.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <kolibrios/syscall.h>
|
||||
#include <kolibrios/dbg.h>
|
||||
|
||||
#define NUM_THREADS 5
|
||||
#define NUM_ITERATIONS 3
|
||||
|
||||
int shared_counter = 0;
|
||||
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
void *
|
||||
thread_function (void *arg)
|
||||
{
|
||||
int thread_id = *(int *)arg;
|
||||
|
||||
for (int i = 0; i < NUM_ITERATIONS; i++)
|
||||
{
|
||||
// Lock mutex
|
||||
pthread_mutex_lock (&mutex);
|
||||
|
||||
// Critical section
|
||||
int temp = shared_counter;
|
||||
__kos_dbg_printf ("I: Thread %d: reading value %d\n", thread_id, temp);
|
||||
|
||||
// Simulate work
|
||||
_ksys (SF_SLEEP, 1); // 10 ms
|
||||
|
||||
temp++;
|
||||
shared_counter = temp;
|
||||
__kos_dbg_printf ("I: Thread %d: writing value %d\n", thread_id,
|
||||
shared_counter);
|
||||
|
||||
// Unlock mutex
|
||||
pthread_mutex_unlock (&mutex);
|
||||
|
||||
_ksys (SF_SLEEP, 5); // 50 ms
|
||||
}
|
||||
|
||||
__kos_dbg_printf ("I: Thread %d completed\n", thread_id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
int rc = 0;
|
||||
pthread_t threads[NUM_THREADS];
|
||||
int thread_ids[NUM_THREADS];
|
||||
|
||||
__kos_dbg_printf ("I: Initial counter value: %d\n", shared_counter);
|
||||
__kos_dbg_printf ("I: Creating %d threads...\n", NUM_THREADS);
|
||||
|
||||
// Create threads
|
||||
for (int i = 0; i < NUM_THREADS; i++)
|
||||
{
|
||||
thread_ids[i] = i + 1;
|
||||
rc = pthread_create (&threads[i], NULL, thread_function, &thread_ids[i]);
|
||||
if (rc)
|
||||
{
|
||||
__kos_dbg_printf ("E: Thread creation error: %s\n", strerror (rc));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for all threads to complete
|
||||
for (int i = 0; i < NUM_THREADS; i++)
|
||||
{
|
||||
rc = pthread_join (threads[i], NULL);
|
||||
if (rc)
|
||||
{
|
||||
__kos_dbg_printf ("E: Thread #%u join error: %s\n", threads[i],
|
||||
strerror (rc));
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
char dbg_prefix = shared_counter == NUM_THREADS * NUM_ITERATIONS ? 'I' : 'E';
|
||||
|
||||
__kos_dbg_printf ("\nI: Final counter value: %d\n", shared_counter);
|
||||
__kos_dbg_printf ("%c: Expected value: %d\n", dbg_prefix, NUM_THREADS * NUM_ITERATIONS);
|
||||
|
||||
// Destroy mutex
|
||||
pthread_mutex_destroy (&mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user