638eeddd2ede6aea9cf6c1473144bb7e982591a1
[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/irq.h>
55
56 #include <drv/timer.h>
57
58 // Global settings for the test.
59 #define MAX_GLOBAL_COUNT            11040
60 #define TEST_TIME_OUT_MS               10
61 #define DELAY                           5
62
63 // Settings for the test message.
64 //Process 0
65 #define INC_PROC_T0                     1
66 #define DELAY_PROC_T0   INC_PROC_T0*DELAY
67 //Process 1
68 #define INC_PROC_T1                     3
69 #define DELAY_PROC_T1   INC_PROC_T1*DELAY
70 //Process 2
71 #define INC_PROC_T2                     5
72 #define DELAY_PROC_T2   INC_PROC_T2*DELAY
73 //Process 3
74 #define INC_PROC_T3                     7
75 #define DELAY_PROC_T3   INC_PROC_T3*DELAY
76 //Process 4
77 #define INC_PROC_T4                    11
78 #define DELAY_PROC_T4   INC_PROC_T4*DELAY
79 //Process 5
80 #define INC_PROC_T5                    13
81 #define DELAY_PROC_T5   INC_PROC_T5*DELAY
82
83 /*
84  * These macros generate the code needed to create the test process functions.
85  */
86 #define RECV_PROC(num, sig) static void receiver_proc##num(void) \
87     { \
88         TestMsg *rec_msg; \
89                 for (;;) \
90         { \
91             sig_wait(sig); \
92             kprintf("Proc[%d]..get message\n", num); \
93             rec_msg = containerof(msg_get(&test_port##num), TestMsg, msg); \
94                         timer_delay(rec_msg->delay); \
95             rec_msg->result += rec_msg->val;  \
96             kprintf("Proc[%d]..process message val[%d],delay[%d],res[%d]\n", num, rec_msg->val, rec_msg->delay, rec_msg->result); \
97             msg_reply(&rec_msg->msg); \
98             kprintf("Proc[%d] reply\n", num); \
99         } \
100     }
101
102 #define SEND_MSG(num) \
103         do { \
104                 kprintf("Main send message to proc[%d]\n", num); \
105                 msg##num.msg.replyPort = &test_portMain; \
106                 msg_put(&test_port##num, &msg##num.msg); \
107         } while(0)
108
109 #define RECV_STACK(num) static cpu_stack_t receiver_stack##num[CONFIG_KERN_MINSTACKSIZE / sizeof(cpu_stack_t)]
110 #define RECV_INIT_PROC(num) proc_new(receiver_proc##num, NULL, sizeof(receiver_stack##num), receiver_stack##num)
111 #define RECV_INIT_MSG(num, proc,sig) msg_initPort(&test_port##num, event_createSignal(proc, sig))
112
113 // A test message with the parameters and a result.
114 typedef struct
115 {
116         Msg msg;
117
118         int val;
119         int delay;
120         int result;
121 } TestMsg;
122
123 // Global count to check if the test is going ok.
124 static int count = 0;
125
126 // Our message port.
127 static MsgPort test_port0;
128 static MsgPort test_port1;
129 static MsgPort test_port2;
130 static MsgPort test_port3;
131 static MsgPort test_port4;
132 static MsgPort test_port5;
133
134 /*
135  * Generate the process to test message.
136  */
137 RECV_PROC(0, SIG_USER0)
138 RECV_PROC(1, SIG_USER1)
139 RECV_PROC(2, SIG_USER2)
140 RECV_PROC(3, SIG_USER3)
141 RECV_PROC(4, SIG_SYSTEM5)
142 RECV_PROC(5, SIG_SYSTEM6)
143 /*
144  * These signal are already use from
145  * main process and the sig_waitWithTimeout functions, so we don't
146  * use it.
147  *
148  * RECV_PROC(6, SIG_SINGLE)
149  * RECV_PROC(7, SIG_TIMEOUT)
150  */
151
152 RECV_STACK(0);
153 RECV_STACK(1);
154 RECV_STACK(2);
155 RECV_STACK(3);
156 RECV_STACK(4);
157 RECV_STACK(5);
158
159 /*
160  * Help function to fill the message to send
161  */
162 static void fill_msg(TestMsg *msg, int val, int delay, int res)
163 {
164         msg->val = val;
165         msg->delay = delay;
166         msg->result = res;
167 }
168
169 /**
170  * Run signal test
171  */
172 int msg_testRun(void)
173 {
174         MsgPort test_portMain;
175         TestMsg msg0;
176         TestMsg msg1;
177         TestMsg msg2;
178         TestMsg msg3;
179         TestMsg msg4;
180         TestMsg msg5;
181         TestMsg *reply;
182
183         // Allocate and start the test process
184     struct Process *recv0 = RECV_INIT_PROC(0);
185     struct Process *recv1 = RECV_INIT_PROC(1);
186     struct Process *recv2 = RECV_INIT_PROC(2);
187     struct Process *recv3 = RECV_INIT_PROC(3);
188     struct Process *recv4 = RECV_INIT_PROC(4);
189     struct Process *recv5 = RECV_INIT_PROC(5);
190
191         kprintf("Run Message test..\n");
192
193         // Init port and message
194     RECV_INIT_MSG(Main, proc_current(), SIG_SINGLE);
195     RECV_INIT_MSG(0, recv0, SIG_USER0);
196     RECV_INIT_MSG(1, recv1, SIG_USER1);
197     RECV_INIT_MSG(2, recv2, SIG_USER2);
198     RECV_INIT_MSG(3, recv3, SIG_USER3);
199     RECV_INIT_MSG(4, recv4, SIG_SYSTEM5);
200     RECV_INIT_MSG(5, recv5, SIG_SYSTEM6);
201
202         // Fill-in first message and send it out.
203         fill_msg(&msg0, INC_PROC_T0, DELAY_PROC_T0, 0);
204         fill_msg(&msg1, INC_PROC_T1, DELAY_PROC_T1, 0);
205         fill_msg(&msg2, INC_PROC_T2, DELAY_PROC_T2, 0);
206         fill_msg(&msg3, INC_PROC_T3, DELAY_PROC_T3, 0);
207         fill_msg(&msg4, INC_PROC_T4, DELAY_PROC_T4, 0);
208         fill_msg(&msg5, INC_PROC_T5, DELAY_PROC_T5, 0);
209
210
211         // Send and wait the message
212         for (int i = 0; i < 23; ++i)
213     {
214                 SEND_MSG(0);
215                 SEND_MSG(1);
216                 SEND_MSG(2);
217                 SEND_MSG(3);
218                 SEND_MSG(4);
219                 SEND_MSG(5);
220                 while(1)
221                 {
222                         if(sig_waitTimeout(SIG_SINGLE, TEST_TIME_OUT_MS) && SIG_SINGLE)
223                         {
224                                 // Wait for a reply...
225                                 reply = containerof(msg_get(&test_portMain), TestMsg, msg);
226                                 if(reply == NULL)
227                                         break;
228                                 count += reply->result;
229                                 kprintf("Main recv[%d] count[%d]\n", reply->result, count);
230                         }
231                 }
232     }
233
234         if(count == MAX_GLOBAL_COUNT)
235         {
236                 kprintf("Message test finished..ok!\n");
237                 return 0;
238         }
239
240         kprintf("Message test finished..fail!\n");
241         return -1;
242 }
243
244 int msg_testSetup(void)
245 {
246         kdbg_init();
247
248         #if CONFIG_KERN_PREEMPT
249                 kprintf("Init Interrupt (preempt mode)..");
250                 irq_init();
251                 kprintf("Done.\n");
252         #endif
253
254         kprintf("Init Timer..");
255         timer_init();
256         kprintf("Done.\n");
257
258         kprintf("Init Process..");
259         proc_init();
260         kprintf("Done.\n");
261         return 0;
262 }
263
264 int msg_testTearDown(void)
265 {
266         kputs("TearDown Message test.\n");
267         return 0;
268 }
269
270 TEST_MAIN(msg);