1 /*
2  * Copyright (c) 2006-2025, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2025-07-03     rcitach      test case for semaphore
9  */
10 
11 #include <rtthread.h>
12 #include <rthw.h>
13 #include <rtdevice.h>
14 #include <utest.h>
15 #include <utest_assert.h>
16 #include <perf_tc.h>
17 
18 static rt_sem_t perf_thread_sem = RT_NULL;
19 static rt_event_t perf_thread_event = RT_NULL;
20 static rt_sem_t complete_sem = RT_NULL;
21 
22 #define EVENT_FLAG          (1 << 0)
perf_thread_sem1(void * parameter)23 static void perf_thread_sem1(void *parameter)
24 {
25     rt_err_t ret = RT_EOK;
26     rt_perf_t *perf = (rt_perf_t *)parameter;
27     rt_event_send(perf_thread_event, EVENT_FLAG);
28     while (1)
29     {
30         ret = rt_sem_take(perf_thread_sem, RT_WAITING_FOREVER);
31         rt_perf_stop(perf);
32         if(ret != RT_EOK)
33         {
34             LOG_E("Sem recv error!");
35             rt_sem_delete(perf_thread_sem);
36             return;
37         }
38 
39         if (perf->count >= UTEST_SYS_PERF_TC_COUNT)
40         {
41             rt_event_delete(perf_thread_event);
42             rt_sem_delete(perf_thread_sem);
43             return;
44         }
45         rt_event_send(perf_thread_event, EVENT_FLAG);
46     }
47 }
48 
perf_thread_sem2(void * parameter)49 static void perf_thread_sem2(void *parameter)
50 {
51     rt_err_t ret = RT_EOK;
52     rt_perf_t *perf = (rt_perf_t *)parameter;
53     rt_uint32_t recv = 0;
54     while (1)
55     {
56         if (perf->count >= UTEST_SYS_PERF_TC_COUNT)
57         {
58             rt_sem_release(complete_sem);
59             return;
60         }
61         ret = rt_event_recv(perf_thread_event, EVENT_FLAG,
62                 (RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR),
63                 RT_WAITING_FOREVER, &recv);
64         if(ret != RT_EOK)
65         {
66             LOG_E("Event reception failed");
67             rt_event_delete(perf_thread_event);
68             rt_sem_release(complete_sem);
69             return;
70         }
71         rt_perf_start(perf);
72         rt_sem_release(perf_thread_sem);
73     }
74 }
75 
rt_perf_thread_sem(rt_perf_t * perf)76 rt_err_t rt_perf_thread_sem(rt_perf_t *perf)
77 {
78     rt_thread_t thread1 = RT_NULL;
79     rt_thread_t thread2 = RT_NULL;
80 
81 # if __STDC_VERSION__ >= 199901L
82     rt_strcpy(perf->name,__func__);
83 #else
84     rt_strcpy(perf->name,"rt_perf_thread_sem");
85 #endif
86 
87     perf_thread_sem = rt_sem_create("perf_thread_sem", 0, RT_IPC_FLAG_FIFO);
88     if (perf_thread_sem == RT_NULL)
89     {
90         LOG_E("perf_thread_sem create failed.");
91         return -RT_ERROR;
92     }
93 
94     perf_thread_event = rt_event_create("perf_thread_event", RT_IPC_FLAG_PRIO);
95     complete_sem = rt_sem_create("complete", 0, RT_IPC_FLAG_FIFO);
96 
97     thread1 = rt_thread_create("perf_thread_sem1", perf_thread_sem1, perf,
98                                 THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE);
99     if (thread1 == RT_NULL)
100     {
101         LOG_E("perf_thread_sem1 create failed.");
102         return -RT_ERROR;
103     }
104 
105     thread2 = rt_thread_create("perf_thread_sem2", perf_thread_sem2, perf,
106                                 THREAD_STACK_SIZE, THREAD_PRIORITY + 1, THREAD_TIMESLICE);
107     if (thread2 == RT_NULL)
108     {
109         LOG_E("perf_thread_sem2 create failed.");
110         return -RT_ERROR;
111     }
112 
113     rt_thread_startup(thread1);
114     rt_thread_startup(thread2);
115 
116     rt_sem_take(complete_sem, RT_WAITING_FOREVER);
117     rt_perf_dump(perf);
118     rt_sem_delete(complete_sem);
119     return RT_EOK;
120 }
121 
122