--- /dev/null
+/*\r
+ * File: cancel5.c\r
+ *\r
+ * Test Synopsis: Test calling pthread_cancel from the main thread\r
+ * without calling pthread_self() in main.\r
+ *\r
+ * Test Method (Validation or Falsification):\r
+ * - \r
+ *\r
+ * Requirements Tested:\r
+ * -\r
+ *\r
+ * Features Tested:\r
+ * - \r
+ *\r
+ * Cases Tested:\r
+ * - \r
+ *\r
+ * Description:\r
+ * - \r
+ *\r
+ * Environment:\r
+ * - \r
+ *\r
+ * Input:\r
+ * - None.\r
+ *\r
+ * Output:\r
+ * - File name, Line number, and failed expression on failure.\r
+ * - No output on success.\r
+ *\r
+ * Assumptions:\r
+ * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock\r
+ * pthread_testcancel, pthread_cancel, pthread_join\r
+ *\r
+ * Pass Criteria:\r
+ * - Process returns zero exit status.\r
+ *\r
+ * Fail Criteria:\r
+ * - Process returns non-zero exit status.\r
+ */\r
+\r
+#include "test.h"\r
+\r
+/*\r
+ * Create NUMTHREADS threads in addition to the Main thread.\r
+ */\r
+enum {\r
+ NUMTHREADS = 10\r
+};\r
+\r
+typedef struct bag_t_ bag_t;\r
+struct bag_t_ {\r
+ int threadnum;\r
+ int started;\r
+ /* Add more per-thread state variables here */\r
+ int count;\r
+};\r
+\r
+static bag_t threadbag[NUMTHREADS + 1];\r
+\r
+void *\r
+mythread(void * arg)\r
+{\r
+ int result = ((int)PTHREAD_CANCELED + 1);\r
+ bag_t * bag = (bag_t *) arg;\r
+\r
+ assert(bag == &threadbag[bag->threadnum]);\r
+ assert(bag->started == 0);\r
+ bag->started = 1;\r
+\r
+ /* Set to known state and type */\r
+\r
+ assert(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) == 0);\r
+\r
+ assert(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) == 0);\r
+\r
+ /*\r
+ * We wait up to 10 seconds, waking every 0.1 seconds,\r
+ * for a cancelation to be applied to us.\r
+ */\r
+ for (bag->count = 0; bag->count < 100; bag->count++)\r
+ Sleep(100);\r
+\r
+ return (void *) result;\r
+}\r
+\r
+int\r
+main()\r
+{\r
+ int failed = 0;\r
+ int i;\r
+ pthread_t t[NUMTHREADS + 1];\r
+\r
+ for (i = 1; i <= NUMTHREADS; i++)\r
+ {\r
+ threadbag[i].started = 0;\r
+ threadbag[i].threadnum = i;\r
+ assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0);\r
+ }\r
+\r
+ /*\r
+ * Code to control or munipulate child threads should probably go here.\r
+ */\r
+ Sleep(500);\r
+\r
+ for (i = 1; i <= NUMTHREADS; i++)\r
+ {\r
+ assert(pthread_cancel(t[i]) == 0);\r
+ }\r
+\r
+ /*\r
+ * Give threads time to run.\r
+ */\r
+ Sleep(NUMTHREADS * 100);\r
+\r
+ /*\r
+ * Standard check that all threads started.\r
+ */\r
+ for (i = 1; i <= NUMTHREADS; i++)\r
+ { \r
+ if (!threadbag[i].started)\r
+ {\r
+ failed |= !threadbag[i].started;\r
+ fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started);\r
+ }\r
+ }\r
+\r
+ assert(!failed);\r
+\r
+ /*\r
+ * Check any results here. Set "failed" and only print output on failure.\r
+ */\r
+ failed = 0;\r
+ for (i = 1; i <= NUMTHREADS; i++)\r
+ {\r
+ int fail = 0;\r
+ int result = 0;\r
+\r
+ /*\r
+ * The thread does not contain any cancelation points, so\r
+ * a return value of PTHREAD_CANCELED confirms that async\r
+ * cancelation succeeded.\r
+ */\r
+ assert(pthread_join(t[i], (void **) &result) == 0);\r
+\r
+ fail = (result != (int) PTHREAD_CANCELED);\r
+\r
+ if (fail)\r
+ {\r
+ fprintf(stderr, "Thread %d: started %d: count %d\n",\r
+ i,\r
+ threadbag[i].started,\r
+ threadbag[i].count);\r
+ }\r
+ failed = (failed || fail);\r
+ }\r
+\r
+ assert(!failed);\r
+\r
+ /*\r
+ * Success.\r
+ */\r
+ return 0;\r
+}\r