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

4.104.115
Last change on this file since e7fb54e was e7fb54e, checked in by Thomas Doerfler <Thomas.Doerfler@…>, on 01/26/10 at 15:09:03

add purge capability to libblock, add proper test case

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