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