Advertisement
alaestor

C89 Hello World Multi-Thread Rand

Sep 10th, 2016
314
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.31 KB | None | 0 0
  1. /*************************
  2.     Alaestor FGL 2016
  3.       Windows 32-bits
  4.      ISO/IEC 9899:1990
  5.      alaestor@null.net
  6. *************************/
  7.  
  8. /*
  9.     Warning and Error Free when compiled with tags ...
  10.     -std=c89 -wall -wextra -O3 -pedantic
  11.     -fexpensive-optimizations -fomit-frame-pointer
  12. */
  13.  
  14. /*
  15.     1 thread per logical core
  16.     each thread randomly generates strings until one makes "Hello World"
  17.     Once successful, the randomly generated string is then printed to stdout
  18. */
  19.  
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <windows.h>
  23. #include <limits.h>
  24.  
  25.  
  26. /* Uncomment DEBUG for Two-Thread, Instant-Solve test */
  27. /* Uncomment PAUSE for the program to prompt for enter key before continuing */
  28. /*#define DEBUG*/
  29. /*#define PAUSE*/
  30. #define LEN (sizeof(str)) /* 12 = 11 chars + 1 null term */
  31.  
  32. /* work return codes (unsigned int) */
  33. #define FAILURE_LOOP_MAX 69
  34. #define FAILURE_FINISHED 9001
  35. #define SUCCESS 1337
  36.  
  37. /* Global Thread State */
  38. unsigned int work_finished;
  39.  
  40. /* Global Constants */
  41. const char chlist[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\0";
  42. const char str[] = "Hello World"; /* may be replaced with anything <max_len */
  43.  
  44. /* Function Prototypes */
  45. unsigned int WINAPI work(void *buffer);
  46. int e(char *errstr);
  47.  
  48. int main(int argc, char **argv)
  49. {
  50.     int i;
  51.     int count = 0;
  52.     int cores = 0;
  53.     unsigned int ec = 0;
  54.     const size_t cache = 64; /* Sys_Logical_Proc_Info ... MinGW Bug */
  55.     const size_t max_len = cache / sizeof(char);
  56.     char *buffers[MAXIMUM_WAIT_OBJECTS];
  57.     HANDLE threads[MAXIMUM_WAIT_OBJECTS];
  58.     SYSTEM_INFO sysinfo;
  59.  
  60.     (void)argc,(void)argv;
  61.     work_finished = 0;
  62.  
  63.     if (LEN >= max_len)
  64.     { /* sanity check */
  65.         e(" String to be generated is over largest cache line");
  66.         return 0;
  67.     }
  68.  
  69.     GetSystemInfo(&sysinfo);
  70.     cores = sysinfo.dwNumberOfProcessors;
  71.  
  72.     #ifdef DEBUG
  73.     cores = 2;
  74.     #endif /* DEBUG */
  75.  
  76.     for (i = 0; i < cores && i < MAXIMUM_WAIT_OBJECTS-1; i++, count++)
  77.     {
  78.         buffers[i] = malloc(cache);
  79.         if (buffers[i] == NULL)
  80.         {
  81.             e(" Malloc returned NULL");
  82.             goto ROUTINE_EXIT;
  83.         }
  84.  
  85.         threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) work,
  86.                                   buffers[i], 0, NULL);
  87.         if (threads[i] == NULL)
  88.         {
  89.             e(" CreateThread returned NULL");
  90.             goto ROUTINE_EXIT;
  91.         }
  92.     }
  93.  
  94.     puts("\n Generating Hello World String...");
  95.     WaitForMultipleObjects(cores, threads, 0, INFINITE);
  96.     puts(" Finished!");
  97.  
  98.     for (i = 0; i < count-1 && ec == 0; i++)
  99.     { /* find the buffer that exited */
  100.         GetExitCodeThread(threads[i], (PDWORD)&ec);
  101.         if (ec != SUCCESS)
  102.             ec = 0;
  103.         else
  104.             ec = i;
  105.     }
  106.  
  107.     /* print generated string */
  108.     printf("\n    %s\n\n",buffers[ec]);
  109.  
  110.     ROUTINE_EXIT: /* goto label: kill existing threads and buffers */
  111.     work_finished = 1;
  112.  
  113.     Sleep(20); /* so threads may have a chance to exit */
  114.  
  115.     for (i = 0; i < count; i++)
  116.     { /* Close thread handles and free associated buffers */
  117.         CloseHandle(threads[i]);
  118.         free(buffers[i]);
  119.     }
  120.  
  121.     #ifdef PAUSE
  122.     puts(" Press Enter To End Process");
  123.     getchar();
  124.     #endif /* PAUSE */
  125.  
  126.     return 0;
  127. }
  128.  
  129. unsigned int WINAPI work(void *buffer)
  130. {
  131.     int i;
  132.     char result[LEN];
  133.     unsigned int loopcount = 0;
  134.  
  135.     do
  136.     { /* Generate random characters in an array to match desired output */
  137.         if (loopcount++ == UINT_MAX-1) /* Oblivion check */
  138.             ExitThread(FAILURE_LOOP_MAX);
  139.  
  140.         if (work_finished == 1) /* another thread has finished */
  141.             ExitThread(FAILURE_FINISHED);
  142.  
  143.         for (i = LEN-1; i >= 0; i--) /* rand characters to compose string */
  144.             result[i] = chlist[rand() % sizeof(chlist) - 1];
  145.  
  146.         #ifdef DEBUG
  147.         memcpy(result, str, LEN);
  148.         #endif /* DEBUG */
  149.  
  150.         Sleep(0); /* So that the thread wont hog timeslices */
  151.     } while (memcmp(&result[0], str, LEN));
  152.  
  153.     memcpy(buffer, (const void *)result, LEN);
  154.  
  155.     ExitThread(SUCCESS);
  156. }
  157.  
  158. int e(char *errstr)
  159. {
  160.     printf("=== ERROR ===\n"
  161.            "%s\n", errstr);
  162.  
  163.     #ifdef PAUSE
  164.     puts(" Press Enter To Continue Application");
  165.     getchar();
  166.     #endif /* PAUSE */
  167.  
  168.     return -1;
  169. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement