ex2.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. */
  9. /* The classic producer-consumer example.
  10. Illustrates mutexes and conditions.
  11. All integers between 0 and 9999 should be printed exactly twice,
  12. once to the right of the arrow and once to the left. */
  13. #include <stdio.h>
  14. #include "pthread.h"
  15. #define BUFFER_SIZE 16
  16. /* Circular buffer of integers. */
  17. struct prodcons
  18. {
  19. int buffer[BUFFER_SIZE]; /* the actual data */
  20. pthread_mutex_t lock; /* mutex ensuring exclusive access to buffer */
  21. int readpos, writepos; /* positions for reading and writing */
  22. pthread_cond_t notempty; /* signaled when buffer is not empty */
  23. pthread_cond_t notfull; /* signaled when buffer is not full */
  24. };
  25. /* Initialize a buffer */
  26. static void init(struct prodcons * b)
  27. {
  28. pthread_mutex_init(&b->lock, NULL);
  29. pthread_cond_init(&b->notempty, NULL);
  30. pthread_cond_init(&b->notfull, NULL);
  31. b->readpos = 0;
  32. b->writepos = 0;
  33. }
  34. /* Store an integer in the buffer */
  35. static void put(struct prodcons * b, int data)
  36. {
  37. pthread_mutex_lock(&b->lock);
  38. /* Wait until buffer is not full */
  39. while ((b->writepos + 1) % BUFFER_SIZE == b->readpos)
  40. {
  41. pthread_cond_wait(&b->notfull, &b->lock);
  42. /* pthread_cond_wait reacquired b->lock before returning */
  43. }
  44. /* Write the data and advance write pointer */
  45. b->buffer[b->writepos] = data;
  46. b->writepos++;
  47. if (b->writepos >= BUFFER_SIZE) b->writepos = 0;
  48. /* Signal that the buffer is now not empty */
  49. pthread_cond_signal(&b->notempty);
  50. pthread_mutex_unlock(&b->lock);
  51. }
  52. /* Read and remove an integer from the buffer */
  53. static int get(struct prodcons * b)
  54. {
  55. int data;
  56. pthread_mutex_lock(&b->lock);
  57. /* Wait until buffer is not empty */
  58. while (b->writepos == b->readpos)
  59. {
  60. pthread_cond_wait(&b->notempty, &b->lock);
  61. }
  62. /* Read the data and advance read pointer */
  63. data = b->buffer[b->readpos];
  64. b->readpos++;
  65. if (b->readpos >= BUFFER_SIZE) b->readpos = 0;
  66. /* Signal that the buffer is now not full */
  67. pthread_cond_signal(&b->notfull);
  68. pthread_mutex_unlock(&b->lock);
  69. return data;
  70. }
  71. /* A test program: one thread inserts integers from 1 to 10000,
  72. the other reads them and prints them. */
  73. #define OVER (-1)
  74. struct prodcons buffer;
  75. static void *producer(void * data)
  76. {
  77. int n;
  78. for (n = 0; n < 10000; n++)
  79. {
  80. printf("%d --->\n", n);
  81. put(&buffer, n);
  82. }
  83. put(&buffer, OVER);
  84. return NULL;
  85. }
  86. static void *consumer(void * data)
  87. {
  88. int d;
  89. while (1)
  90. {
  91. d = get(&buffer);
  92. if (d == OVER) break;
  93. printf("---> %d\n", d);
  94. }
  95. return NULL;
  96. }
  97. int libc_ex2(void)
  98. {
  99. pthread_t th_a, th_b;
  100. void *retval;
  101. init(&buffer);
  102. /* Create the threads */
  103. pthread_create(&th_a, NULL, producer, 0);
  104. pthread_create(&th_b, NULL, consumer, 0);
  105. /* Wait until producer and consumer finish. */
  106. pthread_join(th_a, &retval);
  107. pthread_join(th_b, &retval);
  108. return 0;
  109. }
  110. #include <finsh.h>
  111. FINSH_FUNCTION_EXPORT(libc_ex2, example 2 for libc);