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

4.115
Last change on this file since 796967c was 796967c, checked in by Sebastian Huber <sebastian.huber@…>, on 02/28/12 at 16:19:49

libblock: Change bdbuf API

The functions

o rtems_bdbuf_get(),
o rtems_bdbuf_read(),
o rtems_bdbuf_syncdev(), and
o rtems_bdbuf_purge_dev(),

use now the disk device instead of the device identifier. This makes
bdbuf independent of rtems_disk_obtain() and rtems_disk_release(). It
is the responsiblity of the file system to obtain the disk device. This
also reduces the overhead to get a buffer.

The key for the AVL tree uses now the disk device instead of the device
identifier. The pointer is interpreted as an unsigned integer. This
reduces the memory overhead and makes the comparison operation a bit
faster.

Removed function rtems_bdbuf_purge_major(). This function was too
destructive and could have unpredictable side effects.

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