source: rtems/testsuites/libtests/block10/init.c @ c499856

4.115
Last change on this file since c499856 was c499856, checked in by Chris Johns <chrisj@…>, on 03/20/14 at 21:10:47

Change all references of rtems.com to rtems.org.

  • Property mode set to 100644
File size: 9.5 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup test_bdbuf
5 *
6 * @brief Bdbuf test for purge.
7 */
8
9/*
10 * Copyright (c) 2010
11 * embedded brains GmbH
12 * Obere Lagerstr. 30
13 * D-82178 Puchheim
14 * Germany
15 * <rtems@embedded-brains.de>
16 *
17 * The license and distribution terms for this file may be
18 * found in the file LICENSE in this distribution or at
19 * http://www.rtems.org/license/LICENSE.
20 */
21
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
25
26#include <assert.h>
27#include <errno.h>
28
29#include <rtems.h>
30#include <rtems/bdbuf.h>
31#include <rtems/diskdevs.h>
32#include <rtems/test.h>
33
34#include <bsp.h>
35
36const char rtems_test_name[] = "BLOCK 10";
37
38/* forward declarations to avoid warnings */
39static rtems_task Init(rtems_task_argument argument);
40
41#define ASSERT_SC(sc) assert((sc) == RTEMS_SUCCESSFUL)
42
43#define PRIORITY_HIGH 1
44
45#define PRIORITY_INIT 2
46
47#define PRIORITY_MID 3
48
49#define PRIORITY_SWAPOUT 4
50
51#define PRIORITY_LOW 5
52
53#define PRIORITY_IDLE 6
54
55#define BLOCK_SIZE 1
56
57#define BLOCK_COUNT 1
58
59typedef rtems_bdbuf_buffer *(*access_func)(char task);
60
61typedef void (*release_func)(char task, rtems_bdbuf_buffer *bd);
62
63static rtems_disk_device *dd;
64
65static rtems_id task_id_init;
66
67static rtems_id task_id_purger;
68
69static rtems_id task_id_waiter;
70
71static const rtems_driver_address_table disk_ops = {
72  .initialization_entry = NULL,
73  RTEMS_GENERIC_BLOCK_DEVICE_DRIVER_ENTRIES
74};
75
76static void set_task_prio(rtems_id task, rtems_task_priority prio)
77{
78  rtems_status_code sc = RTEMS_SUCCESSFUL;
79  rtems_task_priority cur = 0;
80
81  sc = rtems_task_set_priority(task, prio, &cur);
82  ASSERT_SC(sc);
83}
84
85static void suspend(rtems_id task)
86{
87  rtems_status_code sc = RTEMS_SUCCESSFUL;
88
89  sc = rtems_task_suspend(task);
90  ASSERT_SC(sc);
91}
92
93static void resume(rtems_id task)
94{
95  rtems_status_code sc = RTEMS_SUCCESSFUL;
96
97  sc = rtems_task_resume(task);
98  ASSERT_SC(sc);
99}
100
101static int disk_ioctl(rtems_disk_device *dd, uint32_t req, void *arg)
102{
103  rtems_status_code sc = RTEMS_SUCCESSFUL;
104
105  if (req == RTEMS_BLKIO_REQUEST) {
106    rtems_blkdev_request *r = arg;
107
108    if (r->req == RTEMS_BLKDEV_REQ_WRITE) {
109      set_task_prio(RTEMS_SELF, PRIORITY_IDLE);
110      set_task_prio(RTEMS_SELF, PRIORITY_SWAPOUT);
111    }
112
113    rtems_blkdev_request_done(r, sc);
114
115    return 0;
116  } else {
117    return rtems_blkdev_ioctl(dd, req, arg);
118  }
119}
120
121static rtems_status_code disk_register(
122  uint32_t block_size,
123  rtems_blkdev_bnum block_count,
124  dev_t *dev_ptr
125)
126{
127  rtems_status_code sc = RTEMS_SUCCESSFUL;
128  rtems_device_major_number major = 0;
129  dev_t dev = 0;
130
131  sc = rtems_io_register_driver(0, &disk_ops, &major);
132  ASSERT_SC(sc);
133
134  dev = rtems_filesystem_make_dev_t(major, 0);
135
136  sc = rtems_disk_create_phys(
137    dev,
138    block_size,
139    block_count,
140    disk_ioctl,
141    NULL,
142    NULL
143  );
144  ASSERT_SC(sc);
145
146  *dev_ptr = dev;
147
148  return RTEMS_SUCCESSFUL;
149}
150
151static rtems_bdbuf_buffer *do_get(char task)
152{
153  rtems_status_code sc = RTEMS_SUCCESSFUL;
154  rtems_bdbuf_buffer *bd = NULL;
155
156  printk("%c: try get\n", task);
157
158  sc = rtems_bdbuf_get(dd, 0, &bd);
159  ASSERT_SC(sc);
160
161  printk("%c: get\n", task);
162
163  return bd;
164}
165
166static rtems_bdbuf_buffer *do_get_mod(char task)
167{
168  rtems_status_code sc = RTEMS_SUCCESSFUL;
169  rtems_bdbuf_buffer *bd = NULL;
170
171  printk("%c: try get modified\n", task);
172
173  sc = rtems_bdbuf_get(dd, 0, &bd);
174  ASSERT_SC(sc);
175
176  sc = rtems_bdbuf_release_modified(bd);
177  ASSERT_SC(sc);
178
179  sc = rtems_bdbuf_get(dd, 0, &bd);
180  ASSERT_SC(sc);
181
182  printk("%c: get modified\n", task);
183
184  return bd;
185}
186
187static rtems_bdbuf_buffer *do_read(char task)
188{
189  rtems_status_code sc = RTEMS_SUCCESSFUL;
190  rtems_bdbuf_buffer *bd = NULL;
191
192  printk("%c: try read\n", task);
193
194  sc = rtems_bdbuf_read(dd, 0, &bd);
195  ASSERT_SC(sc);
196
197  printk("%c: read\n", task);
198
199  return bd;
200}
201
202static void do_rel(char task, rtems_bdbuf_buffer *bd)
203{
204  rtems_status_code sc = RTEMS_SUCCESSFUL;
205
206  printk("%c: release\n", task);
207
208  sc = rtems_bdbuf_release(bd);
209  ASSERT_SC(sc);
210
211  printk("%c: release done\n", task);
212}
213
214static void do_rel_mod(char task, rtems_bdbuf_buffer *bd)
215{
216  rtems_status_code sc = RTEMS_SUCCESSFUL;
217
218  printk("%c: release modified\n", task);
219
220  sc = rtems_bdbuf_release_modified(bd);
221  ASSERT_SC(sc);
222
223  printk("%c: release modified done\n", task);
224}
225
226static void do_sync(char task, rtems_bdbuf_buffer *bd)
227{
228  rtems_status_code sc = RTEMS_SUCCESSFUL;
229
230  printk("%c: sync\n", task);
231
232  sc = rtems_bdbuf_sync(bd);
233  ASSERT_SC(sc);
234
235  printk("%c: sync done\n", task);
236}
237
238static void purge(char task)
239{
240  printk("%c: purge\n", task);
241
242  rtems_bdbuf_purge_dev(dd);
243}
244
245static void task_purger(rtems_task_argument arg)
246{
247  while (true) {
248    suspend(RTEMS_SELF);
249
250    set_task_prio(RTEMS_SELF, PRIORITY_HIGH);
251
252    purge('P');
253  }
254
255  rtems_task_delete(RTEMS_SELF);
256}
257
258static void activate_purger(rtems_task_priority prio)
259{
260  set_task_prio(task_id_purger, prio);
261  resume(task_id_purger);
262}
263
264static void task_waiter(rtems_task_argument arg)
265{
266  while (true) {
267    rtems_bdbuf_buffer *bd = NULL;
268
269    suspend(RTEMS_SELF);
270
271    bd = do_get('W');
272
273    do_rel('W', bd);
274  }
275
276  rtems_task_delete(RTEMS_SELF);
277}
278
279static void create_waiter(void)
280{
281  resume(task_id_waiter);
282  set_task_prio(task_id_waiter, PRIORITY_IDLE);
283}
284
285static void restore_waiter(void)
286{
287  set_task_prio(task_id_waiter, PRIORITY_HIGH);
288}
289
290static void check_access(access_func ac, release_func rel, bool waiter)
291{
292  rtems_bdbuf_buffer *bd = (*ac)('I');
293
294  if (waiter) {
295    create_waiter();
296  }
297
298  purge('I');
299
300  (*rel)('I', bd);
301
302  if (waiter) {
303    restore_waiter();
304  }
305}
306
307static void check_intermediate(release_func rel, bool waiter)
308{
309  rtems_bdbuf_buffer *bd = do_read('I');
310
311  if (waiter) {
312    create_waiter();
313  }
314
315  (*rel)('I', bd);
316
317  purge('I');
318
319  if (waiter) {
320    restore_waiter();
321  }
322}
323
324static void check_transfer(rtems_task_priority prio, bool waiter)
325{
326  rtems_bdbuf_buffer *bd = do_read('I');
327
328  if (waiter) {
329    create_waiter();
330  }
331
332  activate_purger(prio);
333
334  do_sync('I', bd);
335
336  if (waiter) {
337    restore_waiter();
338  }
339}
340
341static const bool waiter_table [] = {
342  true,
343  false
344};
345
346static const access_func access_table [] = {
347  do_get,
348  do_get_mod,
349  do_read
350};
351
352static const release_func release_table [] = {
353  do_rel,
354  do_rel_mod,
355  do_sync
356};
357
358static const rtems_task_priority purger_table [] = {
359  PRIORITY_MID,
360  PRIORITY_LOW
361};
362
363#define ARRAY_COUNT(array) (sizeof(array) / sizeof(array [0]))
364
365#define WAITER_COUNT ARRAY_COUNT(waiter_table)
366
367#define ACCESS_COUNT ARRAY_COUNT(access_table)
368
369#define RELEASE_COUNT ARRAY_COUNT(release_table)
370
371#define PURGER_COUNT ARRAY_COUNT(purger_table)
372
373static const char *waiter_assoc_table [WAITER_COUNT] = {
374  "with waiter",
375  "without waiter"
376};
377
378static const char *access_assoc_table [ACCESS_COUNT] = {
379  "get",
380  "access modified",
381  "read"
382};
383
384static const char *release_assoc_table [RELEASE_COUNT] = {
385  "release",
386  "release modified",
387  "sync"
388};
389
390static const char *purger_assoc_table [PURGER_COUNT] = {
391  "sync",
392  "transfer"
393};
394
395static rtems_task Init(rtems_task_argument argument)
396{
397  rtems_status_code sc = RTEMS_SUCCESSFUL;
398  dev_t dev = 0;
399  size_t i_w = 0;
400  size_t i_ac = 0;
401  size_t i_rel = 0;
402  size_t i_p = 0;
403
404  rtems_test_begink();
405
406  task_id_init = rtems_task_self();
407
408  sc = rtems_disk_io_initialize();
409  ASSERT_SC(sc);
410
411  sc = disk_register(BLOCK_SIZE, BLOCK_COUNT, &dev);
412  ASSERT_SC(sc);
413
414  dd = rtems_disk_obtain(dev);
415  assert(dd != NULL);
416
417  sc = rtems_task_create(
418    rtems_build_name('P', 'U', 'R', 'G'),
419    PRIORITY_HIGH,
420    0,
421    RTEMS_DEFAULT_MODES,
422    RTEMS_DEFAULT_ATTRIBUTES,
423    &task_id_purger
424  );
425  ASSERT_SC(sc);
426
427  sc = rtems_task_start(task_id_purger, task_purger, 0);
428  ASSERT_SC(sc);
429
430  set_task_prio(task_id_purger, PRIORITY_LOW);
431
432  sc = rtems_task_create(
433    rtems_build_name('W', 'A', 'I', 'T'),
434    PRIORITY_HIGH,
435    0,
436    RTEMS_DEFAULT_MODES,
437    RTEMS_DEFAULT_ATTRIBUTES,
438    &task_id_waiter
439  );
440  ASSERT_SC(sc);
441
442  sc = rtems_task_start(task_id_waiter, task_waiter, 0);
443  ASSERT_SC(sc);
444
445  for (i_ac = 0; i_ac < ACCESS_COUNT; ++i_ac) {
446    for (i_rel = 0; i_rel < RELEASE_COUNT; ++i_rel) {
447      for (i_w = 0; i_w < WAITER_COUNT; ++i_w) {
448        printk("test case [access]: %s and %s %s\n", access_assoc_table [i_ac], release_assoc_table [i_rel], waiter_assoc_table [i_w]);
449        check_access(access_table [i_ac], release_table [i_rel], waiter_table [i_w]);
450      }
451    }
452  }
453
454  for (i_rel = 0; i_rel < RELEASE_COUNT; ++i_rel) {
455    for (i_w = 0; i_w < WAITER_COUNT; ++i_w) {
456      printk("test case [intermediate]: %s %s\n", release_assoc_table [i_rel], waiter_assoc_table [i_w]);
457      check_intermediate(release_table [i_rel], waiter_table [i_w]);
458    }
459  }
460
461  for (i_p = 0; i_p < PURGER_COUNT; ++i_p) {
462    for (i_w = 0; i_w < WAITER_COUNT; ++i_w) {
463      printk("test case [transfer]: %s %s\n", purger_assoc_table [i_p], waiter_assoc_table [i_w]);
464      check_transfer(purger_table [i_p], waiter_table [i_w]);
465    }
466  }
467
468  rtems_test_endk();
469
470  exit(0);
471}
472
473#define CONFIGURE_INIT
474
475#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
476#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
477#define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK
478
479#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
480
481#define CONFIGURE_MAXIMUM_TASKS 3
482#define CONFIGURE_MAXIMUM_DRIVERS 4
483
484#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
485
486#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
487
488#define CONFIGURE_INIT_TASK_PRIORITY PRIORITY_INIT
489#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_DEFAULT_ATTRIBUTES
490#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES
491
492#define CONFIGURE_SWAPOUT_TASK_PRIORITY PRIORITY_SWAPOUT
493
494#define CONFIGURE_BDBUF_BUFFER_MIN_SIZE BLOCK_SIZE
495#define CONFIGURE_BDBUF_BUFFER_MAX_SIZE BLOCK_SIZE
496#define CONFIGURE_BDBUF_CACHE_MEMORY_SIZE (BLOCK_SIZE * BLOCK_COUNT)
497
498#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.