source: rtems/testsuites/libtests/block08/bdbuf_tests.h @ 117f7b1

5
Last change on this file since 117f7b1 was 117f7b1, checked in by Sebastian Huber <sebastian.huber@…>, on 08/03/18 at 16:18:56

libtests/block08: Use rtems_blkdev_create()

Update #3358.

  • Property mode set to 100644
File size: 20.0 KB
Line 
1/*! @file
2 * @brief Common declarations of bdbuf tests.
3 *
4 * Copyright (C) 2010 OKTET Labs, St.-Petersburg, Russia
5 * Author: Oleg Kravtsov <Oleg.Kravtsov@oktetlabs.ru>
6 *
7 * The license and distribution terms for this file may be
8 * found in the file LICENSE in this distribution or at
9 * http://www.rtems.org/license/LICENSE.
10 */
11
12#ifndef BDBUF_TESTS_H
13#define BDBUF_TESTS_H
14
15#include <inttypes.h>
16#include <stdio.h>
17#include <string.h>
18#include <errno.h>
19#include <rtems/bspIo.h>
20#include <rtems/bdbuf.h>
21
22#ifdef __cplusplus
23extern "C" {
24#endif
25
26extern void run_bdbuf_tests(void);
27
28extern void bdbuf_test1_1_main(void);
29extern void bdbuf_test1_2_main(void);
30extern void bdbuf_test1_3_main(void);
31extern void bdbuf_test1_4_main(void);
32extern void bdbuf_test1_5_main(void);
33
34extern void bdbuf_test2_1_main(void);
35extern void bdbuf_test2_2_main(void);
36extern void bdbuf_test2_3_main(void);
37extern void bdbuf_test2_4_main(void);
38extern void bdbuf_test2_5_main(void);
39
40extern void bdbuf_test3_1_main(void);
41extern void bdbuf_test3_2_main(void);
42extern void bdbuf_test3_3_main(void);
43
44extern void bdbuf_test4_1_main(void);
45extern void bdbuf_test4_2_main(void);
46extern void bdbuf_test4_3_main(void);
47
48extern rtems_status_code test_disk_initialize(void);
49
50#define ARRAY_NUM(a_) (sizeof(a_) / sizeof(a_[0]))
51
52/**
53 * Configuration parameters of Test disk device.
54 */
55#define TEST_DISK_BLOCK_SIZE   512
56#define TEST_DISK_BLOCK_NUM    1024
57#define TEST_DISK_NAME         "/dev/testdisk"
58
59/** Type of messages between test disk driver and main test task */
60enum bdbuf_test_msg_type {
61    /** Message sent by disk driver to main test task */
62    BDBUF_TEST_MSG_TYPE_DRIVER_REQ,
63    /**
64     * Message sent main test task to disk driver
65     * in reply to request.
66     */
67    BDBUF_TEST_MSG_TYPE_DRIVER_REPLY,
68};
69
70/**
71 * Message used in communication between test disk driver
72 * and main test task.
73 * All R/W requests obtained by driver (from bdbuf library)
74 * are directed to main test task. Then main test task
75 * sends a reply after which test disk driver notifies
76 * bdbuf library about operation complete event.
77 */
78typedef struct bdbuf_test_msg {
79    /** Message type */
80    enum bdbuf_test_msg_type type;
81
82    union {
83        struct driver_req {
84            const rtems_disk_device *dd;
85            uint32_t  req;
86            void     *argp;
87        } driver_req;
88        struct driver_reply {
89            int               ret_val;
90            int               ret_errno;
91            rtems_status_code res_status;
92            int               res_errno;
93        } driver_reply;
94    } val;
95} bdbuf_test_msg;
96
97
98typedef enum bdbuf_rest_thread_prio {
99    BDBUF_TEST_THREAD_PRIO_NORMAL = 3,
100    BDBUF_TEST_THREAD_PRIO_LOW = 7,
101    BDBUF_TEST_THREAD_PRIO_HIGH = 5,
102} bdbuf_rest_thread_prio;
103
104
105typedef struct test_ctx {
106    /**
107     * Message queue used by main task to get messages from
108     * disk device driver.
109     */
110    Objects_Id test_qid;
111
112    /**
113     * Object ID for disk driver queue.
114     * Test task will send messages to this queue in reply
115     * to messages received on @a test_qid.
116     */
117    Objects_Id test_drv_qid;
118
119    /** Test name */
120    const char *test_name;
121
122    /**
123     * Semaphore used for synchronization between test thread
124     * and main test task.
125     * Main test task blocks on one of these semaphores and an auxiliary thread
126     * releases it in order to pass control to main task again.
127     */
128    rtems_id   test_sync_main[3];
129
130    /**
131     * This semaphore is used for synchornization between main test task
132     * and the END of auxiliary threads.
133     */
134    rtems_id   test_end_main;
135
136    /**
137     * Semaphore used for synchronization between test thread
138     * and main test task.
139     * Thread #N blocks on this semaphore and the main task releases it
140     * when it wants to pass control to the auxiliary thread #N.
141     */
142    rtems_id   test_sync[3];
143
144    /** Task Id values of auxiliary threads */
145    Objects_Id test_task[3];
146} test_ctx;
147
148extern test_ctx g_test_ctx;
149
150/** Device ID used for testing */
151extern rtems_disk_device *test_dd;
152
153/**
154 * Create a message queue for test driver that is used for
155 * receiving messages from test task.
156 *
157 * @param[out] id  RTEMS message queue identifier
158 *
159 * @return Status of the operation
160 */
161extern rtems_status_code bdbuf_test_create_drv_rx_queue(Objects_Id *id);
162
163/**
164 * Obtain a message queue for test driver that is used for
165 * sending messages to test task.
166 *
167 * @param[out] id  RTEMS message queue identifier
168 *
169 * @return Status of the operation
170 */
171extern rtems_status_code bdbuf_test_create_drv_tx_queue(Objects_Id *id);
172
173/**
174 * Start a separate test task represented by function @p func
175 * and associated with task index @p idx.
176 *
177 * @param[in] idx   Task index
178 * @param[in] func  Test task function
179 */
180extern rtems_status_code bdbuf_test_start_thread(unsigned int idx,
181                                                 rtems_task_entry func);
182
183/**
184 * Finalize test run.
185 */
186extern rtems_status_code bdbuf_test_end(void);
187
188/** Test result variable */
189extern bool       good_test_result;
190
191#define BDBUF_TEST_BLOCK_TIMEOUT (2 * rtems_clock_get_ticks_per_second())
192
193#define SET_THREAD_PRIORITY(t_num_, prio_) \
194    do {                                                        \
195        rtems_task_priority old_prio;                           \
196        rtems_status_code   rc_;                                \
197                                                                \
198        rc_ = rtems_task_set_priority(                          \
199                g_test_ctx.test_task[(t_num_) - 1],             \
200                BDBUF_TEST_THREAD_PRIO_ ## prio_, &old_prio);   \
201        if (rc_ != RTEMS_SUCCESSFUL)                            \
202        {                                                       \
203            printk("Failed to change priority of test thread #" \
204                   #t_num_ " in test %s\n", g_test_ctx.test_name);         \
205            return;                                             \
206        }                                                       \
207    } while (0)
208
209/**
210 * Start thread number @p t_num_ with @p func_ function
211 * as an entry point of the thread.
212 *
213 * @param t_num_  thread number.
214 * @param func_   thread entry point.
215 */
216#define START_THREAD(t_num_, func_) \
217    do {                                                        \
218        if (bdbuf_test_start_thread((t_num_) - 1, func_) !=     \
219                RTEMS_SUCCESSFUL)                               \
220        {                                                       \
221            return;                                             \
222        }                                                       \
223        printk("Thread #" #t_num_ " started\n");                \
224    } while (0)
225
226/**
227 * Wait for a message from device driver.
228 *
229 * @param[out] msg_  Pointer to a message data structure
230 */
231#define WAIT_DRV_MSG(msg_) \
232    do {                                                        \
233        rtems_status_code rc_;                                  \
234        size_t            msg_size_ = sizeof(*(msg_));          \
235                                                                \
236        rc_ = rtems_message_queue_receive(g_test_ctx.test_qid,  \
237                                          (msg_), &msg_size_,   \
238                                          RTEMS_WAIT,           \
239                                          RTEMS_NO_TIMEOUT);    \
240        if (rc_ != RTEMS_SUCCESSFUL ||                          \
241            msg_size_ != sizeof(*(msg_)))                       \
242        {                                                       \
243            printk("Error at %s:%d\n", __FILE__, __LINE__);     \
244            return;                                             \
245        }                                                       \
246        if ((msg_)->type != BDBUF_TEST_MSG_TYPE_DRIVER_REQ)     \
247        {                                                       \
248            printk("Unexpected message received: %d\n",         \
249                   (msg_)->type);                               \
250            return;                                             \
251        }                                                       \
252    } while (0)
253
254#define WAIT_DRV_MSG_WR(msg_) \
255  do {                                                                     \
256        WAIT_DRV_MSG(msg_);                                                \
257        if ((msg_)->val.driver_req.req != RTEMS_BLKIO_REQUEST ||           \
258            (msg_)->val.driver_req.dd != test_dd ||                        \
259            ((rtems_blkdev_request *)                                      \
260                 ((msg_)->val.driver_req.argp))->req !=                    \
261                 RTEMS_BLKDEV_REQ_WRITE)                                   \
262        {                                                                  \
263            printk("Unexpected message received by disk driver: "          \
264                   "req - 0x%" PRIx32 " (0x%lx), dev - %p (%p)\n", \
265                   (msg_)->val.driver_req.req, RTEMS_BLKIO_REQUEST,        \
266                   (msg_)->val.driver_req.dd, test_dd);                    \
267            return;                                                        \
268        }                                                                  \
269    } while (0)
270
271#define CHECK_NO_DRV_MSG() \
272    do {                                                        \
273        rtems_status_code rc_;                                  \
274        bdbuf_test_msg    msg_;                                 \
275        size_t            msg_size_ = sizeof(msg_);             \
276                                                                \
277        rc_ = rtems_message_queue_receive(g_test_ctx.test_qid,  \
278                  (&msg_), &msg_size_,                          \
279                  RTEMS_WAIT,                                   \
280                  BDBUF_TEST_BLOCK_TIMEOUT);                    \
281        if (rc_ != RTEMS_TIMEOUT)                               \
282        {                                                       \
283            printk("Error at %s:%d\n", __FILE__, __LINE__);     \
284            return;                                             \
285        }                                                       \
286    } while (0)
287
288extern bdbuf_test_msg test_drv_msg;
289
290/**
291 * Send a message to device driver (in order to complete
292 * blocked I/O operation).
293 *
294 * @param ret_val_     Return value to use when returning from
295 *                     ioctl() function.
296 * @param ret_errno_   errno value to set to errno variable.
297 * @param res_status_  In case return value from the ioctl()
298 *                     function is equal to 0, this value
299 *                     is used as status code in asynchronous
300 *                     notification.
301 * @param res_errno_   In case return value from the ioctl()
302 *                     function is equal to 0, this value
303 *                     is used as error value in asynchronous
304 *                     notification.
305 *
306 */
307#define SEND_DRV_MSG(ret_val_, ret_errno_, res_status_, res_errno_) \
308    do {                                                                \
309        rtems_status_code rc_;                                          \
310                                                                        \
311        memset(&test_drv_msg, 0, sizeof(test_drv_msg));                 \
312        test_drv_msg.type = BDBUF_TEST_MSG_TYPE_DRIVER_REPLY;           \
313        test_drv_msg.val.driver_reply.ret_val = (ret_val_);             \
314        test_drv_msg.val.driver_reply.ret_errno = (ret_errno_);         \
315        test_drv_msg.val.driver_reply.res_status = (res_status_);       \
316        test_drv_msg.val.driver_reply.res_errno = (res_errno_);         \
317                                                                        \
318        rc_ = rtems_message_queue_send(g_test_ctx.test_drv_qid,         \
319                                       &test_drv_msg,                   \
320                                       sizeof(test_drv_msg));           \
321        if (rc_ != RTEMS_SUCCESSFUL)                                    \
322        {                                                               \
323            printk("Error while sending a message to "                  \
324                   "disk driver: %u\n", rc_);                           \
325            return;                                                     \
326        }                                                               \
327    } while (0)
328
329/**
330 * Block main test task until a thread passes back control
331 * with CONTINUE_MAIN().
332 *
333 * @param t_num_  thread number from which the main thread
334 *                is waiting for a sync.
335 */
336#define WAIT_THREAD_SYNC(t_num_) \
337    do {                                                                \
338        rtems_status_code rc_;                                          \
339                                                                        \
340        rc_ = rtems_semaphore_obtain(                                   \
341                g_test_ctx.test_sync_main[(t_num_) - 1],                \
342                RTEMS_WAIT, RTEMS_NO_TIMEOUT);                          \
343        if (rc_ != RTEMS_SUCCESSFUL)                                    \
344        {                                                               \
345            printk("Failed to get sync with a thread: %d\n", rc_);      \
346            return;                                                     \
347        }                                                               \
348    } while (0)
349
350/**
351 * Check that a particular thread is blocked.
352 *
353 * @param t_num_  thread number that we want to check for blocking
354 */
355#define CHECK_THREAD_BLOCKED(t_num_) \
356    do {                                                                \
357        rtems_status_code rc_;                                          \
358                                                                        \
359        rc_ = rtems_semaphore_obtain(                                   \
360                g_test_ctx.test_sync_main[(t_num_) - 1],                \
361                RTEMS_WAIT, BDBUF_TEST_BLOCK_TIMEOUT);                  \
362        if (rc_ != RTEMS_TIMEOUT)                                       \
363        {                                                               \
364            printk("Thread %d is not blocked at%s:%d\n",                \
365                   t_num_, __FILE__, __LINE__);                         \
366            return;                                                     \
367        }                                                               \
368    } while (0)
369
370/**
371 * Main test task gives control to the particular thread.
372 *
373 * @param t_num_  thread number to which main test task wants
374 *                to give control.
375 */
376#define CONTINUE_THREAD(t_num_) \
377    do {                                                        \
378        rtems_status_code rc_;                                  \
379                                                                \
380        rc_ = rtems_semaphore_release(                          \
381                g_test_ctx.test_sync[(t_num_) - 1]);            \
382        if (rc_ != RTEMS_SUCCESSFUL)                            \
383        {                                                       \
384            printk("Failed to give control to thread #"         \
385                   #t_num_ ": %d\n", rc_);                      \
386            return;                                             \
387        }                                                       \
388    } while (0)
389
390/**
391 * Passes control back to the main test task from a thread.
392 *
393 * @param t_num_ Current thread number
394 */
395#define CONTINUE_MAIN(t_num_) \
396    do {                                                        \
397        rtems_status_code rc_;                                  \
398                                                                \
399        rc_ = rtems_semaphore_release(                          \
400                g_test_ctx.test_sync_main[(t_num_) - 1]);       \
401        if (rc_ != RTEMS_SUCCESSFUL)                            \
402        {                                                       \
403            printk("Failed to give control to "                 \
404                   "main task: %d", rc_);                       \
405            return;                                             \
406        }                                                       \
407        rc_ = rtems_semaphore_obtain(                           \
408                g_test_ctx.test_sync[(t_num_) - 1],             \
409                RTEMS_WAIT, RTEMS_NO_TIMEOUT);                  \
410        if (rc_ != RTEMS_SUCCESSFUL)                            \
411        {                                                       \
412            printk("Failed to block on thread #"                \
413                   #t_num_ ": %d\n", rc_);                      \
414            return;                                             \
415        }                                                       \
416    } while (0)
417
418#define WAIT_MAIN_SYNC(t_num_) \
419    do {                                                        \
420        rtems_status_code rc_;                                  \
421                                                                \
422        rc_ = rtems_semaphore_obtain(                           \
423                g_test_ctx.test_sync[(t_num_) - 1],             \
424                RTEMS_WAIT, RTEMS_NO_TIMEOUT);                  \
425        if (rc_ != RTEMS_SUCCESSFUL)                            \
426        {                                                       \
427            printk("Failed to block on thread #"                \
428                   #t_num_ ": %d\n", rc_);                      \
429            return;                                             \
430        }                                                       \
431    } while (0)
432
433
434#define TEST_START(test_name_) \
435    do {                                \
436        good_test_result = true;        \
437        g_test_ctx.test_name = test_name_; \
438        printk("%s - STARTED\n",        \
439               g_test_ctx.test_name);              \
440    } while (0)
441
442#define TEST_CHECK_RESULT(step_) \
443    do {                                        \
444        if (!good_test_result)                  \
445        {                                       \
446            printk("TEST FAILED (Step %s)\n",   \
447                   step_);                      \
448            rtems_task_delete(RTEMS_SELF);      \
449        }                                       \
450        else                                    \
451        {                                       \
452            printk("%s: Step %s - OK\n",        \
453                   g_test_ctx.test_name, step_);           \
454        }                                       \
455    } while (0)
456
457#define TEST_STOP() \
458    do {                                 \
459        bdbuf_test_end();                \
460                                         \
461        if (good_test_result)            \
462            printk("TEST PASSED\n");     \
463        else                             \
464            printk("TEST FAILED (END)"); \
465    } while (0)
466
467#define THREAD_END() \
468    do {                                                        \
469        rtems_status_code rc_;                                  \
470                                                                \
471        rc_ = rtems_semaphore_release(g_test_ctx.test_end_main);\
472        if (rc_ != RTEMS_SUCCESSFUL)                            \
473        {                                                       \
474            printk("Failed to give control to "                 \
475                   "main task: %d", rc_);                       \
476            return;                                             \
477        }                                                       \
478        rtems_task_delete(RTEMS_SELF);                          \
479    } while (0)
480
481#define TEST_FAILED() \
482    do {                                \
483        good_test_result = false;       \
484    } while (0)
485
486#define SLEEP() \
487    rtems_task_wake_after(BDBUF_TEST_BLOCK_TIMEOUT)
488
489
490extern rtems_status_code
491bdbuf_test_start_aux_task(rtems_name name,
492                          rtems_task_entry entry_point,
493                          rtems_task_argument arg,
494                          Objects_Id *id);
495#ifdef __cplusplus
496}
497#endif
498
499#endif /* BDBUF_TESTS_H */
Note: See TracBrowser for help on using the repository browser.