Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add an example from the McMini project to test sthread -- currently broken
authorMartin Quinson <martin.quinson@ens-rennes.fr>
Thu, 2 Nov 2023 00:37:35 +0000 (01:37 +0100)
committerMartin Quinson <martin.quinson@ens-rennes.fr>
Thu, 2 Nov 2023 00:54:48 +0000 (01:54 +0100)
I need the feedback of Mathieu on this one, sorry for the inconvenience

teshsuite/mc/CMakeLists.txt
teshsuite/mc/mcmini/barber_shop_ok.c [new file with mode: 0644]
teshsuite/mc/mcmini/barber_shop_ok.tesh [new file with mode: 0644]

index 7addb33..833f214 100644 (file)
@@ -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 (file)
index 0000000..b44a934
--- /dev/null
@@ -0,0 +1,172 @@
+#ifdef _REENTRANT
+#undef _REENTRANT
+#endif
+#define _REENTRANT
+
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+// 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 <Num Customers> <Num Chairs> <rand seed>\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 (file)
index 0000000..1d8b039
--- /dev/null
@@ -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