producer_consumer.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /*
  2. * Copyright (c) 2006-2018, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2018-08-24 yangjie the first version
  9. * 2020-10-17 Meco Man translate to English comment
  10. */
  11. /*
  12. * Demo: producer-consumer problem (or bounded-buffer problem)
  13. *
  14. * this demo creates two threads to demonstrate producer-consumer problem:
  15. * 1) producer thread: adds 1 to the variable "cnt" and stores it into the array.
  16. * 2) consumer thread: prints out the value and adds it up
  17. *
  18. * read more:
  19. * https://www.rt-thread.io/document/site/thread-sync/thread-sync/#semaphores
  20. */
  21. #include <rtthread.h>
  22. #define THREAD_PRIORITY 6
  23. #define THREAD_STACK_SIZE 512
  24. #define THREAD_TIMESLICE 5
  25. /* define the maximum 5 elements can be produced */
  26. #define MAXSEM 5
  27. rt_uint32_t array[MAXSEM];
  28. /* the pointers of producer and consumer's position in the array */
  29. static rt_uint32_t set, get;
  30. /* thread handler */
  31. static rt_thread_t producer_tid = RT_NULL;
  32. static rt_thread_t consumer_tid = RT_NULL;
  33. struct rt_semaphore sem_lock;
  34. struct rt_semaphore sem_empty, sem_full;
  35. /* producer thread entry function */
  36. void producer_thread_entry(void *parameter)
  37. {
  38. int cnt = 0;
  39. while (cnt < 10)
  40. {
  41. /* get a "empty" mark */
  42. rt_sem_take(&sem_empty, RT_WAITING_FOREVER);
  43. /* protect the critial section */
  44. rt_sem_take(&sem_lock, RT_WAITING_FOREVER);
  45. array[set % MAXSEM] = cnt + 1;
  46. rt_kprintf("the producer generates a number: %d\n", array[set % MAXSEM]);
  47. set++;
  48. rt_sem_release(&sem_lock);
  49. /* release a "full" mark */
  50. rt_sem_release(&sem_full);
  51. cnt++;
  52. rt_thread_mdelay(20);
  53. }
  54. rt_kprintf("the producer exit!\n");
  55. }
  56. /* consumer thread entry function */
  57. void consumer_thread_entry(void *parameter)
  58. {
  59. rt_uint32_t sum = 0;
  60. while (1)
  61. {
  62. /* get a "full" mark */
  63. rt_sem_take(&sem_full, RT_WAITING_FOREVER);
  64. /* protect the critial section */
  65. rt_sem_take(&sem_lock, RT_WAITING_FOREVER);
  66. sum += array[get % MAXSEM];
  67. rt_kprintf("the consumer[%d] get a number: %d\n", (get % MAXSEM), array[get % MAXSEM]);
  68. get++;
  69. rt_sem_release(&sem_lock);
  70. /* release a "empty" mark */
  71. rt_sem_release(&sem_empty);
  72. if (get == 10) break;
  73. rt_thread_mdelay(50);
  74. }
  75. rt_kprintf("the consumer sum is: %d\n", sum);
  76. rt_kprintf("the consumer exit!\n");
  77. }
  78. int producer_consumer(void)
  79. {
  80. set = 0;
  81. get = 0;
  82. rt_sem_init(&sem_lock, "lock", 1, RT_IPC_FLAG_FIFO);
  83. rt_sem_init(&sem_empty, "empty", MAXSEM, RT_IPC_FLAG_FIFO);
  84. rt_sem_init(&sem_full, "full", 0, RT_IPC_FLAG_FIFO);
  85. producer_tid = rt_thread_create("producer",
  86. producer_thread_entry, RT_NULL,
  87. THREAD_STACK_SIZE,
  88. THREAD_PRIORITY - 1, THREAD_TIMESLICE);
  89. if (producer_tid != RT_NULL)
  90. rt_thread_startup(producer_tid);
  91. consumer_tid = rt_thread_create("consumer",
  92. consumer_thread_entry, RT_NULL,
  93. THREAD_STACK_SIZE,
  94. THREAD_PRIORITY + 1, THREAD_TIMESLICE);
  95. if (consumer_tid != RT_NULL)
  96. rt_thread_startup(consumer_tid);
  97. return 0;
  98. }
  99. /* export the msh command */
  100. MSH_CMD_EXPORT(producer_consumer, producer_consumer sample);