From: Martin Quinson Date: Thu, 2 Nov 2023 00:37:35 +0000 (+0100) Subject: Add an example from the McMini project to test sthread -- currently broken X-Git-Tag: v3.35~89^2~22^2~9 X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/commitdiff_plain/e665a7a968591345ebb4ce0ee948910b5a0e0af1?ds=sidebyside Add an example from the McMini project to test sthread -- currently broken I need the feedback of Mathieu on this one, sorry for the inconvenience --- diff --git a/teshsuite/mc/CMakeLists.txt b/teshsuite/mc/CMakeLists.txt index 7addb33912..833f2149fb 100644 --- a/teshsuite/mc/CMakeLists.txt +++ b/teshsuite/mc/CMakeLists.txt @@ -56,3 +56,38 @@ ENDIF() if(enable_coverage) ADD_TEST(cover-mc-mutex-handling ${CMAKE_CURRENT_BINARY_DIR}/mutex-handling/mutex-handling ${CMAKE_HOME_DIRECTORY}/examples/platforms/small_platform.xml) endif() + + +if("${CMAKE_SYSTEM}" MATCHES "Linux") + foreach(x +# barber_shop_deadlock producer_consumer_deadlock +# simple_cond_broadcast_deadlock simple_semaphore_deadlock simple_barrier_deadlock simple_cond_deadlock +# simple_semaphores_deadlock +# philosophers_mutex_deadlock +# philosophers_semaphores_deadlock +# philosophers_spurious_deadlock +# simple_barrier_with_threads_deadlock +# simple_semaphores_with_threads_deadlock +# simple_cond_broadcast_with_semaphore_deadlock1 simple_cond_broadcast_with_semaphore_deadlock2 +# simple_mutex_deadlock +# simple_mutex_with_threads_deadlock + + barber_shop_ok +# philosophers_mutex_ok philosophers_semaphores_ok +# producer_consumer_ok producer_consumer_spurious_nok +# simple_barrier_ok simple_barrier_with_threads_ok simple_cond_broadcast_ok +# simple_cond_broadcast_with_semaphore_ok simple_cond_ok simple_mutex_ok +# simple_mutex_with_threads_ok simple_semaphores_ok simple_semaphores_with_threads_ok simple_threads_ok + ) + + add_executable (mcmini-${x} EXCLUDE_FROM_ALL mcmini/${x}.c) + set_target_properties(mcmini-${x} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/mcmini) + target_link_libraries(mcmini-${x} PRIVATE Threads::Threads) + add_dependencies(tests-mc mcmini-${x}) + if(SIMGRID_HAVE_STATEFUL_MC) # Only needed to introspect the binary + target_link_libraries(mc-mini-${x} PUBLIC "-Wl,-znorelro -Wl,-znoseparate-code") # TODO: convert to target_link_option once CMAKE_VERSION is >3.13 + endif() + + ADD_TESH_FACTORIES(mc-mini-${x} "^thread" --setenv libdir=${CMAKE_BINARY_DIR}/lib --setenv bindir=${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/mcmini/${x}.tesh) + endforeach() +endif() \ No newline at end of file diff --git a/teshsuite/mc/mcmini/barber_shop_ok.c b/teshsuite/mc/mcmini/barber_shop_ok.c new file mode 100644 index 0000000000..b44a934f1b --- /dev/null +++ b/teshsuite/mc/mcmini/barber_shop_ok.c @@ -0,0 +1,172 @@ +#ifdef _REENTRANT +#undef _REENTRANT +#endif +#define _REENTRANT + +#include +#include +#include +#include +#include + +// The maximum number of customer threads. +#define MAX_CUSTOMERS 25 + +// Define the semaphores. + +// waitingRoom Limits the # of customers allowed +// to enter the waiting room at one time. +sem_t waitingRoom; + +// barberChair ensures mutually exclusive access to +// the barber chair. +sem_t barberChair; + +// barberPillow is used to allow the barber to sleep +// until a customer arrives. +sem_t barberPillow; + +// seatBelt is used to make the customer to wait until +// the barber is done cutting his/her hair. +sem_t seatBelt; + +// Flag to stop the barber thread when all customers +// have been serviced. +int allDone = 0; + +static void randwait(int secs) +{ + int len; + + // Generate a random number... + len = (int)((drand48() * secs) + 1); + sleep(len); +} + +static void* customer(void* number) +{ + int num = *(int*)number; + + // Leave for the shop and take some random amount of + // time to arrive. + printf("Customer %d leaving for barber shop.\n", num); + randwait(5); + printf("Customer %d arrived at barber shop.\n", num); + + // Wait for space to open up in the waiting room... + sem_wait(&waitingRoom); + printf("Customer %d entering waiting room.\n", num); + + // Wait for the barber chair to become free. + sem_wait(&barberChair); + + // The chair is free so give up your spot in the + // waiting room. + sem_post(&waitingRoom); + + // Wake up the barber... + printf("Customer %d waking the barber.\n", num); + sem_post(&barberPillow); + + // Wait for the barber to finish cutting your hair. + sem_wait(&seatBelt); + + // Give up the chair. + sem_post(&barberChair); + printf("Customer %d leaving barber shop.\n", num); + return NULL; +} + +static void* barber(void* junk) +{ + // While there are still customers to be serviced... + // Our barber is omnicient and can tell if there are + // customers still on the way to his shop. + while (!allDone) { + + // Sleep until someone arrives and wakes you.. + printf("The barber is sleeping\n"); + sem_wait(&barberPillow); + + // Skip this stuff at the end... + if (!allDone) { + + // Take a random amount of time to cut the + // customer's hair. + printf("The barber is cutting hair\n"); + randwait(3); + printf("The barber has finished cutting hair.\n"); + + // Release the customer when done cutting... + sem_post(&seatBelt); + } else { + printf("The barber is going home for the day.\n"); + } + } + return NULL; +} + +int main(int argc, char* argv[]) +{ + pthread_t btid; + pthread_t tid[MAX_CUSTOMERS]; + long RandSeed; + int i, numCustomers, numChairs; + int Number[MAX_CUSTOMERS]; + + // Check to make sure there are the right number of + // command line arguments. + if (argc != 4) { + printf("Use: SleepBarber \n"); + exit(-1); + } + + // Get the command line arguments and convert them + // into integers. + numCustomers = atoi(argv[1]); + numChairs = atoi(argv[2]); + RandSeed = atol(argv[3]); + + // Make sure the number of threads is less than the number of + // customers we can support. + if (numCustomers > MAX_CUSTOMERS) { + printf("The maximum number of Customers is %d.\n", MAX_CUSTOMERS); + exit(-1); + } + + printf("\nSleepBarber.c\n\n"); + printf("A solution to the sleeping barber problem using semaphores.\n"); + + // Initialize the random number generator with a new seed. + srand48(RandSeed); + + // Initialize the numbers array. + for (i = 0; i < MAX_CUSTOMERS; i++) { + Number[i] = i; + } + + // Initialize the semaphores with initial values... + sem_init(&waitingRoom, 0, numChairs); + sem_init(&barberChair, 0, 1); + sem_init(&barberPillow, 0, 0); + sem_init(&seatBelt, 0, 0); + + // Create the barber. + pthread_create(&btid, NULL, barber, NULL); + + // Create the customers. + for (i = 0; i < numCustomers; i++) { + pthread_create(&tid[i], NULL, customer, (void*)&Number[i]); + } + + // Join each of the threads to wait for them to finish. + for (i = 0; i < numCustomers; i++) { + pthread_join(tid[i], NULL); + } + + // When all of the customers are finished, kill the + // barber thread. + allDone = 1; + sem_post(&barberPillow); // Wake the barber so he will exit. + pthread_join(btid, NULL); +} diff --git a/teshsuite/mc/mcmini/barber_shop_ok.tesh b/teshsuite/mc/mcmini/barber_shop_ok.tesh new file mode 100644 index 0000000000..1d8b039d18 --- /dev/null +++ b/teshsuite/mc/mcmini/barber_shop_ok.tesh @@ -0,0 +1,4 @@ +# We ignore the LD_PRELOAD lines from the expected output because they contain the build path +! ignore .*LD_PRELOAD.* + +$ $VALGRIND_NO_TRACE_CHILDREN ${bindir:=.}/../../bin/simgrid-mc --cfg=model-check/setenv:LD_PRELOAD=${libdir:=.}/libsgmalloc.so:${libdir:=.}/libsthread.so ${bindir:=.}/mcmini/mcmini-barber_shop_ok 5 3 0