Merge branch "preempt" in "trunk".
[bertos.git] / bertos / kern / msg_test.c
1 /**
2  * \file
3  * <!--
4  * This file is part of BeRTOS.
5  *
6  * Bertos is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  * As a special exception, you may use this file as part of a free software
21  * library without restriction.  Specifically, if other files instantiate
22  * templates or use macros or inline functions from this file, or you compile
23  * this file and link it with other files to produce an executable, this
24  * file does not by itself cause the resulting executable to be covered by
25  * the GNU General Public License.  This exception does not however
26  * invalidate any other reasons why the executable file might be covered by
27  * the GNU General Public License.
28  *
29  * Copyright 2004, 2008 Develer S.r.l. (http://www.develer.com/)
30  * Copyright 1999, 2000, 2001 Bernie Innocenti <bernie@codewiz.org>
31  * -->
32  *
33  * \brief Message test.
34  *
35  * \version $Id$
36  *
37  * \author Daniele Basile <asterix@develer.com>
38  *
39  * $test$: cp bertos/cfg/cfg_proc.h $cfgdir/
40  * $test$: echo  "#undef CONFIG_KERN" >> $cfgdir/cfg_proc.h
41  * $test$: echo "#define CONFIG_KERN 1" >> $cfgdir/cfg_proc.h
42  * $test$: cp bertos/cfg/cfg_signal.h $cfgdir/
43  * $test$: echo  "#undef CONFIG_KERN_SIGNALS" >> $cfgdir/cfg_signal.h
44  * $test$: echo "#define CONFIG_KERN_SIGNALS 1" >> $cfgdir/cfg_signal.h
45  */
46
47 #include "cfg/cfg_timer.h"
48 #include <cfg/debug.h>
49 #include <cfg/test.h>
50 #include <cfg/compiler.h>
51
52 #include <kern/msg.h>
53 #include <kern/proc.h>
54 #include <kern/signal.h>
55
56 #include <mware/event.h>
57
58 #include <drv/timer.h>
59
60 /*
61  * In the nightly build test, signals are disables, so this
62  * code won't compile.
63  * Since this code is used when we run "make check" it will be
64  * compiled and therefor tested there.
65  */
66 #if CONFIG_KERN_SIGNALS
67
68
69 // Global settings for the test.
70 #define MAX_GLOBAL_COUNT            11040
71 #define TEST_TIME_OUT_MS             5000
72 #define DELAY                           5
73
74 // Settings for the test message.
75 //Process 0
76 #define INC_PROC_T0                     1
77 #define DELAY_PROC_T0   INC_PROC_T0*DELAY
78 //Process 1
79 #define INC_PROC_T1                     3
80 #define DELAY_PROC_T1   INC_PROC_T1*DELAY
81 //Process 2
82 #define INC_PROC_T2                     5
83 #define DELAY_PROC_T2   INC_PROC_T2*DELAY
84 //Process 3
85 #define INC_PROC_T3                     7
86 #define DELAY_PROC_T3   INC_PROC_T3*DELAY
87 //Process 4
88 #define INC_PROC_T4                    11
89 #define DELAY_PROC_T4   INC_PROC_T4*DELAY
90 //Process 5
91 #define INC_PROC_T5                    13
92 #define DELAY_PROC_T5   INC_PROC_T5*DELAY
93
94 /*
95  * These macros generate the code needed to create the test process functions.
96  */
97 #define RECV_PROC(num, sig) \
98 static NORETURN void receiver_proc##num(void) \
99 { \
100         TestMsg *rec_msg; \
101         for(;;) \
102         { \
103                 sig_wait(sig); \
104                 kprintf("Proc[%d]..get message\n", num); \
105                 rec_msg = containerof(msg_get(&test_port##num), TestMsg, msg); \
106                 timer_delay(rec_msg->delay); \
107                 rec_msg->result += rec_msg->val; \
108                 kprintf("Proc[%d]..process message val[%d],delay[%d],res[%d]\n", num, rec_msg->val, rec_msg->delay, rec_msg->result); \
109                 msg_reply(&rec_msg->msg); \
110                 process_num++; \
111                 kprintf("Proc[%d] reply\n", num); \
112         } \
113 }
114
115 #define SEND_MSG(num) \
116         do { \
117                 kprintf("Main send message to proc[%d]\n", num); \
118                 msg##num.msg.replyPort = &test_portMain; \
119                 msg_put(&test_port##num, &msg##num.msg); \
120         } while(0)
121
122 #define RECV_STACK(num) PROC_DEFINE_STACK(receiver_stack##num, KERN_MINSTACKSIZE * 2)
123 #define RECV_INIT_PROC(num) proc_new(receiver_proc##num, NULL, sizeof(receiver_stack##num), receiver_stack##num)
124 #define RECV_INIT_MSG(num, proc, sig) msg_initPort(&test_port##num, event_createSignal(proc, sig))
125
126 // A test message with the parameters and a result.
127 typedef struct
128 {
129         Msg msg;
130
131         int val;
132         int delay;
133         int result;
134 } TestMsg;
135
136 // Global count to check if the test is going ok.
137 static int count = 0;
138 static int process_num;
139
140 // Our message port.
141 static MsgPort test_port0;
142 static MsgPort test_port1;
143 static MsgPort test_port2;
144 static MsgPort test_port3;
145 static MsgPort test_port4;
146 static MsgPort test_port5;
147
148 /*
149  * Generate the process to test message.
150  */
151 RECV_PROC(0, SIG_USER0)
152 RECV_PROC(1, SIG_USER1)
153 RECV_PROC(2, SIG_USER2)
154 RECV_PROC(3, SIG_USER3)
155 RECV_PROC(4, SIG_SYSTEM5)
156 RECV_PROC(5, SIG_SYSTEM6)
157 /*
158  * These signal are already use from
159  * main process and the sig_waitWithTimeout functions, so we don't
160  * use it.
161  *
162  * RECV_PROC(6, SIG_SINGLE)
163  * RECV_PROC(7, SIG_TIMEOUT)
164  */
165
166 RECV_STACK(0);
167 RECV_STACK(1);
168 RECV_STACK(2);
169 RECV_STACK(3);
170 RECV_STACK(4);
171 RECV_STACK(5);
172
173 /*
174  * Help function to fill the message to send
175  */
176 static void fill_msg(TestMsg *msg, int val, int delay, int res)
177 {
178         msg->val = val;
179         msg->delay = delay;
180         msg->result = res;
181 }
182
183 /**
184  * Run signal test
185  */
186 int msg_testRun(void)
187 {
188         MsgPort test_portMain;
189         TestMsg msg0;
190         TestMsg msg1;
191         TestMsg msg2;
192         TestMsg msg3;
193         TestMsg msg4;
194         TestMsg msg5;
195         TestMsg *reply;
196
197         // Allocate and start the test process
198     struct Process *recv0 = RECV_INIT_PROC(0);
199     struct Process *recv1 = RECV_INIT_PROC(1);
200     struct Process *recv2 = RECV_INIT_PROC(2);
201     struct Process *recv3 = RECV_INIT_PROC(3);
202     struct Process *recv4 = RECV_INIT_PROC(4);
203     struct Process *recv5 = RECV_INIT_PROC(5);
204
205         kprintf("Run Message test..\n");
206
207         // Init port and message
208     RECV_INIT_MSG(Main, proc_current(), SIG_SINGLE);
209     RECV_INIT_MSG(0, recv0, SIG_USER0);
210     RECV_INIT_MSG(1, recv1, SIG_USER1);
211     RECV_INIT_MSG(2, recv2, SIG_USER2);
212     RECV_INIT_MSG(3, recv3, SIG_USER3);
213     RECV_INIT_MSG(4, recv4, SIG_SYSTEM5);
214     RECV_INIT_MSG(5, recv5, SIG_SYSTEM6);
215
216         // Fill-in first message and send it out.
217         fill_msg(&msg0, INC_PROC_T0, DELAY_PROC_T0, 0);
218         fill_msg(&msg1, INC_PROC_T1, DELAY_PROC_T1, 0);
219         fill_msg(&msg2, INC_PROC_T2, DELAY_PROC_T2, 0);
220         fill_msg(&msg3, INC_PROC_T3, DELAY_PROC_T3, 0);
221         fill_msg(&msg4, INC_PROC_T4, DELAY_PROC_T4, 0);
222         fill_msg(&msg5, INC_PROC_T5, DELAY_PROC_T5, 0);
223
224
225         // Send and wait the message
226         for (int i = 0; i < 23; ++i)
227     {
228                 process_num = 0;
229                 SEND_MSG(0);
230                 SEND_MSG(1);
231                 SEND_MSG(2);
232                 SEND_MSG(3);
233                 SEND_MSG(4);
234                 SEND_MSG(5);
235                 while(1)
236                 {
237                         sigmask_t sigs = sig_waitTimeout(SIG_SINGLE, ms_to_ticks(TEST_TIME_OUT_MS));
238                         if (sigs & SIG_SINGLE)
239                         {
240                                 // Wait for a reply...
241                                 while ((reply = (TestMsg *)msg_get(&test_portMain)))
242                                 {
243                                         count += reply->result;
244                                         kprintf("Main recv[%d] count[%d]\n", reply->result, count);
245                                 }
246                         }
247                         
248                         if (process_num == 6)
249                                 break;
250
251                         if (sigs & SIG_TIMEOUT)
252                         {
253                                 kputs("Main: sig timeout\n");
254                                 goto error;
255                         }
256                 }
257     }
258
259         if(count == MAX_GLOBAL_COUNT)
260         {
261                 kprintf("Message test finished..ok!\n");
262                 return 0;
263         }
264         
265 error:
266         kprintf("Message test finished..fail!\n");
267         return -1;
268 }
269
270 int msg_testSetup(void)
271 {
272         kdbg_init();
273
274         kprintf("Init Timer..");
275         timer_init();
276         kprintf("Done.\n");
277
278         kprintf("Init Process..");
279         proc_init();
280         kprintf("Done.\n");
281         return 0;
282 }
283
284 int msg_testTearDown(void)
285 {
286         kputs("TearDown Message test.\n");
287         return 0;
288 }
289
290 TEST_MAIN(msg);
291
292 #endif /* CONFIG_KERN_SIGNALS */