1 /*
2  * Copyright (c) 2015-2016 Wind River Systems, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /**
18  * @file C++ Synchronization demo.  Uses basic C++ functionality.
19  */
20 
21 #include <stdio.h>
22 #include <zephyr.h>
23 #include <arch/cpu.h>
24 #include <sys/printk.h>
25 
26 /**
27  * @class semaphore the basic pure virtual semaphore class
28  */
29 class semaphore {
30 public:
31 	virtual int wait(void) = 0;
32 	virtual int wait(int timeout) = 0;
33 	virtual void give(void) = 0;
34 };
35 
36 /* specify delay between greetings (in ms); compute equivalent in ticks */
37 #define SLEEPTIME  500
38 #define STACKSIZE 2000
39 
40 struct k_thread coop_thread;
41 K_THREAD_STACK_DEFINE(coop_stack, STACKSIZE);
42 
43 /*
44  * @class cpp_semaphore
45  * @brief Semaphore
46  *
47  * Class derives from the pure virtual semaphore class and
48  * implements it's methods for the semaphore
49  */
50 class cpp_semaphore: public semaphore {
51 protected:
52 	struct k_sem _sema_internal;
53 public:
54 	cpp_semaphore();
~cpp_semaphore()55 	virtual ~cpp_semaphore() {}
56 	virtual int wait(void);
57 	virtual int wait(int timeout);
58 	virtual void give(void);
59 };
60 
61 /*
62  * @brief cpp_semaphore basic constructor
63  */
cpp_semaphore()64 cpp_semaphore::cpp_semaphore()
65 {
66 	printk("Create semaphore %p\n", this);
67 	k_sem_init(&_sema_internal, 0, K_SEM_MAX_LIMIT);
68 }
69 
70 /*
71  * @brief wait for a semaphore
72  *
73  * Test a semaphore to see if it has been signaled.  If the signal
74  * count is greater than zero, it is decremented.
75  *
76  * @return 1 when semaphore is available
77  */
wait(void)78 int cpp_semaphore::wait(void)
79 {
80 	k_sem_take(&_sema_internal, K_FOREVER);
81 	return 1;
82 }
83 
84 /*
85  * @brief wait for a semaphore within a specified timeout
86  *
87  * Test a semaphore to see if it has been signaled.  If the signal
88  * count is greater than zero, it is decremented. The function
89  * waits for timeout specified
90  *
91  * @param timeout the specified timeout in ticks
92  *
93  * @return 1 if semaphore is available, 0 if timed out
94  */
wait(int timeout)95 int cpp_semaphore::wait(int timeout)
96 {
97 	return k_sem_take(&_sema_internal, K_MSEC(timeout));
98 }
99 
100 /**
101  *
102  * @brief Signal a semaphore
103  *
104  * This routine signals the specified semaphore.
105  *
106  * @return N/A
107  */
give(void)108 void cpp_semaphore::give(void)
109 {
110 	k_sem_give(&_sema_internal);
111 }
112 
113 cpp_semaphore sem_main;
114 cpp_semaphore sem_coop;
115 
coop_thread_entry(void)116 void coop_thread_entry(void)
117 {
118 	struct k_timer timer;
119 
120 	k_timer_init(&timer, NULL, NULL);
121 
122 	while (1) {
123 		/* wait for main thread to let us have a turn */
124 		sem_coop.wait();
125 
126 		/* say "hello" */
127 		printk("%s: Hello World!\n", __FUNCTION__);
128 
129 		/* wait a while, then let main thread have a turn */
130 		k_timer_start(&timer, K_MSEC(SLEEPTIME), K_NO_WAIT);
131 		k_timer_status_sync(&timer);
132 		sem_main.give();
133 	}
134 }
135 
main(void)136 int main(void)
137 {
138 	struct k_timer timer;
139 
140 	k_thread_create(&coop_thread, coop_stack, STACKSIZE,
141 			(k_thread_entry_t) coop_thread_entry,
142 			NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT);
143 	k_timer_init(&timer, NULL, NULL);
144 
145 	while (1) {
146 		/* say "hello" */
147 		printk("%s: Hello World!\n", __FUNCTION__);
148 
149 		/* wait a while, then let coop thread have a turn */
150 		k_timer_start(&timer, K_MSEC(SLEEPTIME), K_NO_WAIT);
151 		k_timer_status_sync(&timer);
152 		sem_coop.give();
153 
154 		/* Wait for coop thread to let us have a turn */
155 		sem_main.wait();
156 	}
157 
158 	return 0;
159 }
160