ex5.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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, implemented with semaphores.
  10. All integers between 0 and 9999 should be printed exactly twice,
  11. once to the right of the arrow and once to the left. */
  12. #include <stdio.h>
  13. #include "pthread.h"
  14. #include "semaphore.h"
  15. #define BUFFER_SIZE 16
  16. /* Circular buffer of integers. */
  17. struct prodcons {
  18. int buffer[BUFFER_SIZE]; /* the actual data */
  19. int readpos, writepos; /* positions for reading and writing */
  20. sem_t sem_read; /* number of elements available for reading */
  21. sem_t sem_write; /* number of locations available for writing */
  22. };
  23. /* Initialize a buffer */
  24. void init(struct prodcons * b)
  25. {
  26. sem_init(&b->sem_write, 0, BUFFER_SIZE - 1);
  27. sem_init(&b->sem_read, 0, 0);
  28. b->readpos = 0;
  29. b->writepos = 0;
  30. }
  31. /* Store an integer in the buffer */
  32. void put(struct prodcons * b, int data)
  33. {
  34. /* Wait until buffer is not full */
  35. sem_wait(&b->sem_write);
  36. /* Write the data and advance write pointer */
  37. b->buffer[b->writepos] = data;
  38. b->writepos++;
  39. if (b->writepos >= BUFFER_SIZE) b->writepos = 0;
  40. /* Signal that the buffer contains one more element for reading */
  41. sem_post(&b->sem_read);
  42. }
  43. /* Read and remove an integer from the buffer */
  44. int get(struct prodcons * b)
  45. {
  46. int data;
  47. /* Wait until buffer is not empty */
  48. sem_wait(&b->sem_read);
  49. /* Read the data and advance read pointer */
  50. data = b->buffer[b->readpos];
  51. b->readpos++;
  52. if (b->readpos >= BUFFER_SIZE) b->readpos = 0;
  53. /* Signal that the buffer has now one more location for writing */
  54. sem_post(&b->sem_write);
  55. return data;
  56. }
  57. /* A test program: one thread inserts integers from 1 to 10000,
  58. the other reads them and prints them. */
  59. #define OVER (-1)
  60. struct prodcons buffer;
  61. static void *producer(void * data)
  62. {
  63. int n;
  64. for (n = 0; n < 10000; n++) {
  65. printf("%d --->\n", n);
  66. put(&buffer, n);
  67. }
  68. put(&buffer, OVER);
  69. return NULL;
  70. }
  71. static void *consumer(void * data)
  72. {
  73. int d;
  74. while (1) {
  75. d = get(&buffer);
  76. if (d == OVER) break;
  77. printf("---> %d\n", d);
  78. }
  79. return NULL;
  80. }
  81. int libc_ex5(void)
  82. {
  83. pthread_t th_a, th_b;
  84. void * retval;
  85. init(&buffer);
  86. /* Create the threads */
  87. pthread_create(&th_a, NULL, producer, 0);
  88. pthread_create(&th_b, NULL, consumer, 0);
  89. /* Wait until producer and consumer finish. */
  90. pthread_join(th_a, &retval);
  91. pthread_join(th_b, &retval);
  92. return 0;
  93. }
  94. #include <finsh.h>
  95. FINSH_FUNCTION_EXPORT(libc_ex5, example 5 for libc);