ex2.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  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. int buffer[BUFFER_SIZE]; /* the actual data */
  19. pthread_mutex_t lock; /* mutex ensuring exclusive access to buffer */
  20. int readpos, writepos; /* positions for reading and writing */
  21. pthread_cond_t notempty; /* signaled when buffer is not empty */
  22. pthread_cond_t notfull; /* signaled when buffer is not full */
  23. };
  24. /* Initialize a buffer */
  25. static void init(struct prodcons * b)
  26. {
  27. pthread_mutex_init(&b->lock, NULL);
  28. pthread_cond_init(&b->notempty, NULL);
  29. pthread_cond_init(&b->notfull, NULL);
  30. b->readpos = 0;
  31. b->writepos = 0;
  32. }
  33. /* Store an integer in the buffer */
  34. static void put(struct prodcons * b, int data)
  35. {
  36. pthread_mutex_lock(&b->lock);
  37. /* Wait until buffer is not full */
  38. while ((b->writepos + 1) % BUFFER_SIZE == b->readpos) {
  39. pthread_cond_wait(&b->notfull, &b->lock);
  40. /* pthread_cond_wait reacquired b->lock before returning */
  41. }
  42. /* Write the data and advance write pointer */
  43. b->buffer[b->writepos] = data;
  44. b->writepos++;
  45. if (b->writepos >= BUFFER_SIZE) b->writepos = 0;
  46. /* Signal that the buffer is now not empty */
  47. pthread_cond_signal(&b->notempty);
  48. pthread_mutex_unlock(&b->lock);
  49. }
  50. /* Read and remove an integer from the buffer */
  51. static int get(struct prodcons * b)
  52. {
  53. int data;
  54. pthread_mutex_lock(&b->lock);
  55. /* Wait until buffer is not empty */
  56. while (b->writepos == b->readpos) {
  57. pthread_cond_wait(&b->notempty, &b->lock);
  58. }
  59. /* Read the data and advance read pointer */
  60. data = b->buffer[b->readpos];
  61. b->readpos++;
  62. if (b->readpos >= BUFFER_SIZE) b->readpos = 0;
  63. /* Signal that the buffer is now not full */
  64. pthread_cond_signal(&b->notfull);
  65. pthread_mutex_unlock(&b->lock);
  66. return data;
  67. }
  68. /* A test program: one thread inserts integers from 1 to 10000,
  69. the other reads them and prints them. */
  70. #define OVER (-1)
  71. struct prodcons buffer;
  72. static void * producer(void * data)
  73. {
  74. int n;
  75. for (n = 0; n < 10000; n++) {
  76. printf("%d --->\n", n);
  77. put(&buffer, n);
  78. }
  79. put(&buffer, OVER);
  80. return NULL;
  81. }
  82. static void * consumer(void * data)
  83. {
  84. int d;
  85. while (1) {
  86. d = get(&buffer);
  87. if (d == OVER) break;
  88. printf("---> %d\n", d);
  89. }
  90. return NULL;
  91. }
  92. int libc_ex2(void)
  93. {
  94. pthread_t th_a, th_b;
  95. void * retval;
  96. init(&buffer);
  97. /* Create the threads */
  98. pthread_create(&th_a, NULL, producer, 0);
  99. pthread_create(&th_b, NULL, consumer, 0);
  100. /* Wait until producer and consumer finish. */
  101. pthread_join(th_a, &retval);
  102. pthread_join(th_b, &retval);
  103. return 0;
  104. }
  105. #include <finsh.h>
  106. FINSH_FUNCTION_EXPORT(libc_ex2, example 2 for libc);