1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-05 08:46:02 +02:00
cdt/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/data/launch/src/MultiThread.cc
Simon Marchi 0f94c4a067 debug tests: Add thread compatibility layer and use it
Having a compatibility layer for threading operations, like the one we
have for sleep, will allow removing a lot of platform dependent code in
the test sources, therefore simplifying the tests themselves.

I changed MultiThread.cc and MultiThreadRunControl.cc as examples, but
there are other tests files that could benefit from it.

I also changed MultiThread.cc to remove all the synchronization based on
sleeps. It now works using thread barriers, which should make the tests
less prone to random failure (although I don't think these ones were
particularly flaky) and run faster (since we don't wait for nothing).

The fallouts of that change on the Java part of the tests are taken care
of as well.

Change-Id: I7be86a5727877638c0ff0a489d263ee6bbe84764
Signed-off-by: Simon Marchi <simon.marchi@polymtl.ca>
Reviewed-on: https://git.eclipse.org/r/36814
Reviewed-by: Marc Khouzam <marc.khouzam@ericsson.com>
Tested-by: Hudson CI
Tested-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Reviewed-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
2015-01-07 12:36:59 -05:00

104 lines
2.6 KiB
C++

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include "Sleep.h"
#include "Thread.h"
static const int NUM_THREADS = 5;
struct PrintHelloArgs {
int thread_id;
ThreadBarrier *barrier_start;
ThreadBarrier *barrier_finish;
ThreadSemaphore *sem_start;
};
static ThreadRet THREAD_CALL_CONV PrintHello(void *void_arg)
{
struct PrintHelloArgs *args = (struct PrintHelloArgs *) void_arg;
int thread_id = args->thread_id;
ThreadBarrier *barrier_start = args->barrier_start;
ThreadBarrier *barrier_finish = args->barrier_finish;
ThreadSemaphore *sem_start = args->sem_start;
/* Indicate to main thread that the thread is started. */
ThreadSemaphorePut(sem_start);
printf("Hello World! It's me, thread #%d!\n", thread_id);
/* Make sure that all threads are started before the breakpoint in main hits. */
ThreadBarrierWait(barrier_start);
printf("Thread %d in the middle\n", thread_id);
/* Make sure that the thread does not finish before the breakpoint in main hits. */
ThreadBarrierWait(barrier_finish);
printf("Goodbye World! From thread #%d\n", thread_id);
return THREAD_DEFAULT_RET;
}
int main(int argc, char *argv[])
{
ThreadHandle threads[NUM_THREADS];
struct PrintHelloArgs args[NUM_THREADS];
/* Used to make rendez-vous points between all threads. */
ThreadBarrier barrier_start;
ThreadBarrier barrier_finish;
/* Used to tell when a thread is started for real. */
ThreadSemaphore sem_start;
/* + 1 for main thread */
ThreadBarrierInit(&barrier_start, NUM_THREADS + 1);
ThreadBarrierInit(&barrier_finish, NUM_THREADS + 1);
ThreadSemaphoreInit(&sem_start, 0);
for (int t = 0; t < NUM_THREADS; t++)
{
printf("In main: creating thread #%d\n", t);
args[t].thread_id = t;
args[t].barrier_start = &barrier_start;
args[t].barrier_finish = &barrier_finish;
args[t].sem_start = &sem_start;
int ret = StartThread(PrintHello, &args[t], &threads[t]);
if (!ret)
{
printf("Error: StartThread failed.\n");
exit(-1);
}
/* Wait until the thread has really started. */
ThreadSemaphoreTake(&sem_start);
printf("In main: thread #%d has started\n", t); /* Breakpoint LINE_MAIN_AFTER_THREAD_START */
}
/* Let the threads continue to the 'critical' section> */
ThreadBarrierWait(&barrier_start);
printf("In main thread, all threads created.\n"); /* main breakpoint here */
SLEEP(30);
/* Unlock the threads and let the program finish. */
ThreadBarrierWait(&barrier_finish);
for (int t = 0; t < NUM_THREADS; t++)
{
printf("In main, joining thread #%d\n", t);
JoinThread(threads[t], NULL);
}
ThreadBarrierDestroy(&barrier_start);
ThreadBarrierDestroy(&barrier_finish);
ThreadSemaphoreDestroy(&sem_start);
return 0;
}