source: rtems/testsuites/libtests/block06/init.c @ d093934

4.104.11
Last change on this file since d093934 was d093934, checked in by Ralf Corsepius <ralf.corsepius@…>, on Nov 13, 2009 at 9:47:57 AM

2009-11-13 Ralf Corsépius <ralf.corsepius@…>

  • block06/init.c: Add missing prototype.
  • Property mode set to 100644
File size: 42.7 KB
Line 
1/*
2 * Copyright 2008 Chris Johns (chrisj@rtems.org)
3 *
4 * The license and distribution terms for this file may be
5 * found in the file LICENSE in this distribution or at
6 * http://www.rtems.com/license/LICENSE.
7 *
8 * $Id$
9 */
10
11/**
12 * BD Buffer test.
13 *
14 * Please add more tests
15 */
16
17#include <errno.h>
18#include <setjmp.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <sys/types.h>
22#include <sys/stat.h>
23#include <inttypes.h>
24
25#include <rtems.h>
26#include <rtems/chain.h>
27#include <rtems/error.h>
28#include <rtems/bdbuf.h>
29
30#define BDBUF_DISKS 2
31#define BDBUF_SIZE  1024
32
33#if 0
34const rtems_bdbuf_config rtems_bdbuf_configuration =
35{
36  5,           /* max_read_ahead_blocks */
37  5,           /* max_write_blocks */
38  15,          /* swapout_priority */
39  250,         /* swapout_period */
40  1000,        /* swap_block_hold */
41  0,           /* swapout_workers */
42  15,          /* swapout_worker_priority */
43  1024 * 1024, /* size */
44  512,         /* buffer_min */
45  4096         /* buffer_max */
46};
47#endif
48
49/**
50 * Let the IO system allocation the next available major number.
51 */
52#define RTEMS_DRIVER_AUTO_MAJOR (0)
53
54/**
55 * The bdbuf disk driver base name.
56 */
57#define BDBUF_DISK_DEVICE_BASE_NAME "/dev/bddisk"
58
59/**
60 * The actions the disk driver handles.
61 */
62typedef enum bdbuf_disk_action
63{
64  BDBUF_DISK_NOOP,
65  BDBUF_DISK_WAIT,
66  BDBUF_DISK_SLEEP,
67  BDBUF_DISK_BLOCKS_INORDER
68} bdbuf_disk_action;
69
70/**
71 * The BDBUF Disk driver.
72 */
73typedef struct bdbuf_disk
74{
75  const char*       name;
76  rtems_id          lock;
77  uint32_t          block_size;
78  uint32_t          block_count;
79  bdbuf_disk_action driver_action;
80  const char*       watcher_name;
81  rtems_id          watcher;
82  int               watch_count;
83  const char*       waiting_name;
84  rtems_id          waiting;
85  uint32_t          driver_sleep;
86} bdbuf_disk;
87
88/*
89 * A disk drive for each pool.
90 */
91static bdbuf_disk bdbuf_disks[BDBUF_DISKS];
92
93/**
94 * Task control.
95 */
96typedef struct bdbuf_task_control
97{
98  bool                      die;
99  const char*               name;
100  rtems_id                  task;
101  rtems_id                  master;
102  int                       test;
103  rtems_device_major_number major;
104  rtems_device_minor_number minor;
105  bool                      passed;
106} bdbuf_task_control;
107
108#define BDBUF_TEST_TASKS (3)
109
110/**
111 * Seconds as milli-seconds.
112 */
113#define BDBUF_SECONDS(msec) ((msec) * 1000UL)
114
115/**
116 * Print a message to output and flush it.
117 *
118 * @param format The format string. See printf for details.
119 * @param ... The arguments for the format text.
120 * @return int The number of bytes written to the output.
121 */
122static int
123bdbuf_test_printf (const char *format, ...)
124{
125  int ret = 0;
126  va_list args;
127  va_start (args, format);
128  ret =  vfprintf (stdout, format, args);
129  fflush (stdout);
130  return ret;
131}
132
133/**
134 * Print the status code description and return true if true.
135 *
136 * @param sc The RTEMS status code.
137 * @retval true The status code is successful.
138 * @retval false The status code is not successful.
139 */
140static bool
141bdbuf_test_print_sc (rtems_status_code sc, bool newline)
142{
143  if (newline)
144    fprintf (stdout, "%s\n", rtems_status_text (sc));
145  else
146    fprintf (stdout, "%s", rtems_status_text (sc));
147  return sc == RTEMS_SUCCESSFUL;
148}
149
150/**
151 * BDBuf disk device driver lock.
152 */
153static bool
154bdbuf_disk_lock (bdbuf_disk* bdd)
155{
156  rtems_status_code sc;
157  sc = rtems_semaphore_obtain (bdd->lock, RTEMS_WAIT, 0);
158  if (sc != RTEMS_SUCCESSFUL)
159  {
160    bdbuf_test_printf ("disk ioctl: lock failed: ");
161    bdbuf_test_print_sc (sc, true);
162    return false;
163  }
164  return true;
165}
166
167/**
168 * BDBuf disk device driver unlock.
169 */
170static bool
171bdbuf_disk_unlock (bdbuf_disk* bdd)
172{
173  rtems_status_code sc;
174  sc = rtems_semaphore_release (bdd->lock);
175  if (sc != RTEMS_SUCCESSFUL)
176  {
177    bdbuf_test_printf ("disk ioctl: unlock failed: ");
178    bdbuf_test_print_sc (sc, true);
179    return false;
180  }
181  return true;
182}
183
184/**
185 * BDBUf wait for the wait event.
186 */
187rtems_status_code
188bdbuf_wait (const char* who, unsigned long timeout)
189{
190  rtems_status_code sc;
191  rtems_event_set   out;
192  sc = rtems_event_receive (RTEMS_EVENT_0,
193                            RTEMS_WAIT | RTEMS_EVENT_ANY,
194                            TOD_MICROSECONDS_TO_TICKS (timeout * 1000),
195                            &out);
196  if (sc != RTEMS_SUCCESSFUL)
197  {
198    bdbuf_test_printf ("%s: wait: receive failed: ", who);
199    bdbuf_test_print_sc (sc, true);
200  }
201  else if ((out & RTEMS_EVENT_0) == 0)
202  {
203    bdbuf_test_printf ("%s: wait: received wrong event: %08x", who, out);
204  }
205  return sc;
206}
207
208/**
209 * BDBUf send wait event.
210 */
211static bool
212bdbuf_send_wait_event (const char* task, const char* msg, rtems_id id)
213{
214  bdbuf_test_printf ("%s: %s: %08x: ", task, msg, id);
215  return  bdbuf_test_print_sc (rtems_event_send (id, RTEMS_EVENT_0), true);
216}
217
218/**
219 * BDBUf wait for the wait event.
220 */
221static rtems_status_code
222bdbuf_watch (unsigned long timeout)
223{
224  rtems_status_code sc;
225  rtems_event_set   out;
226  sc = rtems_event_receive (RTEMS_EVENT_1,
227                            RTEMS_WAIT | RTEMS_EVENT_ANY,
228                            TOD_MICROSECONDS_TO_TICKS (timeout * 1000),
229                            &out);
230  if (sc != RTEMS_SUCCESSFUL)
231  {
232    bdbuf_test_printf ("watch: receive failed: ");
233    bdbuf_test_print_sc (sc, true);
234  }
235  else if ((out & RTEMS_EVENT_1) == 0)
236  {
237    bdbuf_test_printf ("watch: received wrong event: %08x", out);
238  }
239  return sc;
240}
241
242/**
243 * BDBUf send wait event.
244 */
245static bool
246bdbuf_send_watch_event (const char* task, const char* msg, rtems_id id)
247{
248  bdbuf_test_printf ("%s: %s: %08x: ", task, msg, id);
249  return  bdbuf_test_print_sc (rtems_event_send (id, RTEMS_EVENT_1), true);
250}
251
252/**
253 * Set up a disk driver watch.
254 */
255static void
256bdbuf_set_disk_driver_watch (bdbuf_task_control* tc, int count)
257{
258  /*
259   * Set up a disk watch and wait for the write to happen.
260   */
261  bdbuf_disk_lock (&bdbuf_disks[tc->minor]);
262  bdbuf_disks[tc->minor].watcher_name = tc->name;
263  bdbuf_disks[tc->minor].watcher = tc->task;
264  bdbuf_disks[tc->minor].watch_count = count;
265  bdbuf_disk_unlock (&bdbuf_disks[tc->minor]);
266}
267
268/**
269 * Clear the disk driver watch.
270 */
271static void
272bdbuf_clear_disk_driver_watch (bdbuf_task_control* tc)
273{
274  /*
275   * Set up a disk watch and wait for the write to happen.
276   */
277  bdbuf_disk_lock (&bdbuf_disks[tc->minor]);
278  bdbuf_disks[tc->minor].watcher_name = 0;
279  bdbuf_disks[tc->minor].watcher = 0;
280  bdbuf_disks[tc->minor].watch_count = 0;
281  bdbuf_disk_unlock (&bdbuf_disks[tc->minor]);
282}
283
284/**
285 * Wait for the disk driver watch.
286 */
287static bool
288bdbuf_disk_driver_watch_wait (bdbuf_task_control* tc, unsigned long msecs)
289{
290  bool              passed = true;
291  rtems_status_code sc = bdbuf_watch (msecs);
292  if (sc != RTEMS_SUCCESSFUL)
293  {
294    bdbuf_test_printf ("%s: driver watch: driver wait: ", tc->name);
295    passed = bdbuf_test_print_sc (sc, true);
296  }
297  bdbuf_clear_disk_driver_watch (tc);
298  return passed;
299}
300
301/**
302 * Set the disk driver action.
303 */
304static void
305bdbuf_set_disk_driver_action (bdbuf_task_control* tc, bdbuf_disk_action action)
306{
307  /*
308   * Set up a disk action.
309   */
310  bdbuf_disk_lock (&bdbuf_disks[tc->minor]);
311  bdbuf_disks[tc->minor].driver_action = action;
312  bdbuf_disk_unlock (&bdbuf_disks[tc->minor]);
313}
314
315/**
316 * BDBUF Sleep.
317 */
318static bool
319bdbuf_sleep (unsigned long msecs)
320{
321  rtems_status_code sc;
322  sc = rtems_task_wake_after (TOD_MICROSECONDS_TO_TICKS (msecs * 1000));
323  if (sc != RTEMS_SUCCESSFUL)
324  {
325    bdbuf_test_printf ("sleep wake after failed: ");
326    bdbuf_test_print_sc (sc, true);
327    return false;
328  }
329  return true;
330}
331
332/**
333 * Initialise a task control.
334 */
335static void
336bdbuf_task_control_init (int                       task,
337                         bdbuf_task_control*       tc,
338                         rtems_id                  master,
339                         rtems_device_major_number major)
340{
341  char name[6];
342  sprintf (name, "bdt%d", task);
343 
344  tc->die    = false;
345  tc->name   = strdup (name); /* leaks */
346  tc->task   = 0;
347  tc->master = master;
348  tc->test   = 0;
349  tc->major  = major;
350  tc->minor  = 0;
351  tc->passed = false;
352}
353
354static bool
355bdbuf_disk_ioctl_watcher (bdbuf_disk* bdd, int update)
356{
357  /*
358   * Always wake the watcher.
359   */
360  if (bdd->watcher)
361  {
362    if (bdd->watch_count)
363    {
364      if (update > bdd->watch_count)
365        bdd->watch_count -= update;
366      else
367        bdd->watch_count = 0;
368    }
369   
370    if (bdd->watch_count == 0)
371    {
372      bdbuf_send_watch_event (bdd->watcher_name,
373                              "disk ioctl: wake watcher",
374                              bdd->watcher);
375      bdd->watcher = 0;
376    }
377  }
378 
379  return true;
380}
381
382
383static bool
384bdbuf_disk_ioctl_process (bdbuf_disk* bdd, rtems_blkdev_request* req)
385{
386  bool result = true;
387  int  b;
388 
389  /*
390   * Perform the requested action.
391   */
392  switch (bdd->driver_action)
393  {
394    case BDBUF_DISK_NOOP:
395      break;
396     
397    case BDBUF_DISK_WAIT:
398      if (bdd->waiting)
399        bdbuf_test_printf ("disk ioctl: bad waiter: %s:%08x\n",
400                           bdd->waiting_name, bdd->waiting);
401      bdd->waiting_name = "bdd";
402
403      bdd->waiting = rtems_task_self ();
404
405      if (bdbuf_disk_unlock (bdd))
406        result = bdbuf_wait (bdd->name, 0) == RTEMS_SUCCESSFUL;
407      else
408        result = false;
409
410      /*
411       * Ignore any error if one happens.
412       */
413      bdbuf_disk_lock (bdd);
414      break;
415
416    case BDBUF_DISK_SLEEP:
417      bdbuf_test_printf ("disk ioctl: sleeping: %d msecs\n",
418                         bdd->driver_sleep);
419      result = bdbuf_sleep (bdd->driver_sleep);
420      break;
421
422    case BDBUF_DISK_BLOCKS_INORDER:
423      bdbuf_test_printf ("disk ioctl: multi-block order check: count = %d\n",
424                         req->bufnum);
425      for (b = 0; b < (req->bufnum - 1); b++)
426        if (req->bufs[b].block >= req->bufs[b + 1].block)
427          bdbuf_test_printf ("disk ioctl: out of order: index:%d (%d >= %d\n",
428                             b, req->bufs[b].block, req->bufs[b + 1].block);
429      break;
430
431    default:
432      bdbuf_test_printf ("disk ioctl: invalid action: %d\n",
433                         bdd->driver_action);
434      result = false;
435      break;
436  }
437
438  return result;
439}
440
441static bool
442bdbuf_disk_ioctl_leave (bdbuf_disk* bdd, int buffer_count)
443{
444  /*
445   * Handle the watcher.
446   */
447  bdbuf_disk_ioctl_watcher (bdd, buffer_count);
448 
449  return true;
450}
451
452/**
453 * BDBuf disk IOCTL handler.
454 *
455 * @param dd Disk device.
456 * @param req IOCTL request code.
457 * @param argp IOCTL argument.
458 * @retval The IOCTL return value
459 */
460static int
461bdbuf_disk_ioctl (rtems_disk_device *dd, uint32_t req, void* argp)
462{
463  rtems_blkdev_request *r = argp;
464  bdbuf_disk           *bdd = rtems_disk_driver_data (dd);
465
466  errno = 0;
467 
468  if (!bdbuf_disk_lock (bdd))
469  {
470    errno = EIO;
471  }
472  else
473  {
474    switch (req)
475    {
476      case RTEMS_BLKIO_REQUEST:
477        switch (r->req)
478        {
479          case RTEMS_BLKDEV_REQ_READ:
480            if (!bdbuf_disk_ioctl_process (bdd, r))
481              errno = EIO;
482            else
483            {
484              rtems_blkdev_sg_buffer* sg = r->bufs;
485              uint32_t                block = RTEMS_BLKDEV_START_BLOCK (r);
486              uint32_t                b;
487              int32_t                 remains;
488
489              remains = r->bufnum * bdd->block_size;
490
491              for (b = 0; b < r->bufnum; b++, block++, sg++)
492              {
493                uint32_t length = sg->length;
494
495                if (sg->length != bdd->block_size)
496                  if (length > bdd->block_size)
497                    length = bdd->block_size;
498
499                memset (sg->buffer, block, length);
500
501                remains -= length;
502              }
503
504              r->req_done (r->done_arg, RTEMS_SUCCESSFUL, 0);
505            }
506            bdbuf_disk_ioctl_leave (bdd, r->bufnum);
507            break;
508           
509          case RTEMS_BLKDEV_REQ_WRITE:
510            if (!bdbuf_disk_ioctl_process (bdd, r))
511              errno = EIO;
512            r->req_done (r->done_arg, RTEMS_SUCCESSFUL, 0);
513            bdbuf_disk_ioctl_leave (bdd, r->bufnum);
514            break;
515           
516          default:
517            errno = EBADRQC;
518            break;
519        }
520        break;
521
522      default:
523        errno = EBADRQC;
524        break;
525    }
526
527    if (!bdbuf_disk_unlock (bdd))
528      errno = EIO;
529  }
530
531  return errno == 0 ? 0 : -1;
532}
533
534/**
535 * BDBuf disk device driver initialization.
536 *
537 * @param major Disk major device number.
538 * @param minor Minor device number, not applicable.
539 * @param arg Initialization argument, not applicable.
540 */
541static rtems_device_driver
542bdbuf_disk_initialize (rtems_device_major_number major,
543                       rtems_device_minor_number minor,
544                       void*                     arg)
545{
546  rtems_status_code sc;
547 
548  bdbuf_test_printf ("disk io init: ");
549  sc = rtems_disk_io_initialize ();
550  if (!bdbuf_test_print_sc (sc, true))
551    return sc;
552 
553  for (minor = 0; minor < BDBUF_DISKS; minor++)
554  {
555    char              name[sizeof (BDBUF_DISK_DEVICE_BASE_NAME) + 10];
556    bdbuf_disk*       bdd = &bdbuf_disks[minor];
557    rtems_status_code sc;
558
559    snprintf (name, sizeof (name),
560              BDBUF_DISK_DEVICE_BASE_NAME "%" PRIu32, minor);
561
562    bdd->name = strdup (name);
563   
564    bdbuf_test_printf ("disk init: %s\n", bdd->name);
565    bdbuf_test_printf ("disk lock: ");
566
567    sc = rtems_semaphore_create (rtems_build_name ('B', 'D', 'D', 'K'), 1,
568                                 RTEMS_PRIORITY | RTEMS_BINARY_SEMAPHORE |
569                                 RTEMS_INHERIT_PRIORITY, 0, &bdd->lock);
570    if (!bdbuf_test_print_sc (sc, true))
571      return RTEMS_IO_ERROR;
572
573    bdd->block_size  = 512 * (minor + 1);
574    bdd->block_count = BDBUF_SIZE * (minor + 1);
575
576    sc = rtems_disk_create_phys(rtems_filesystem_make_dev_t (major, minor),
577                                bdd->block_size, bdd->block_count,
578                                bdbuf_disk_ioctl, bdd, name);
579    if (sc != RTEMS_SUCCESSFUL)
580    {
581      bdbuf_test_printf ("disk init: create phys failed: ");
582      bdbuf_test_print_sc (sc, true);
583      return sc;
584    }
585   
586  }
587  return RTEMS_SUCCESSFUL;
588}
589
590/**
591 * Create the RAM Disk Driver entry.
592 */
593static rtems_driver_address_table bdbuf_disk_io_ops = {
594  initialization_entry: bdbuf_disk_initialize,
595  open_entry:           rtems_blkdev_generic_open,
596  close_entry:          rtems_blkdev_generic_close,
597  read_entry:           rtems_blkdev_generic_read,
598  write_entry:          rtems_blkdev_generic_write,
599  control_entry:        rtems_blkdev_generic_ioctl
600};
601
602/**
603 * Set up the disk.
604 */
605
606static bool
607bdbuf_tests_setup_disk (rtems_device_major_number* major)
608{
609  rtems_status_code sc;
610 
611  /*
612   * Register the disk driver.
613   */
614  bdbuf_test_printf ("register disk driver\n");
615
616  sc = rtems_io_register_driver (RTEMS_DRIVER_AUTO_MAJOR,
617                                 &bdbuf_disk_io_ops,
618                                 major);
619 
620  return sc == RTEMS_SUCCESSFUL;
621}
622
623static bool
624bdbuf_tests_create_task (bdbuf_task_control* tc,
625                         rtems_task_priority priority,
626                         rtems_task_entry    entry_point)
627{
628  rtems_status_code sc;
629
630  bdbuf_test_printf ("creating task: %s: priority: %d: ",
631                     tc->name, priority);
632 
633  sc = rtems_task_create (rtems_build_name (tc->name[0], tc->name[1],
634                                            tc->name[2], tc->name[3]),
635                          priority,
636                          8 * 1024,
637                          RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,
638                          RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR,
639                          &tc->task);
640  if (!bdbuf_test_print_sc (sc, true))
641    return false;
642 
643  bdbuf_test_printf ("starting task: %s: ", tc->name);
644 
645  sc = rtems_task_start (tc->task, entry_point, (rtems_task_argument) tc);
646
647  return bdbuf_test_print_sc (sc, true);
648}
649
650/**
651 * Get the block 0 buffer twice. The first time it is requested it
652 * will be taken from the empty list and returned to the LRU list.
653 * The second time it will be removed from the LRU list.
654 */
655static void
656bdbuf_tests_task_0_test_1 (bdbuf_task_control* tc)
657{
658  rtems_status_code   sc;
659  bool                passed;
660  int                 i;
661  rtems_bdbuf_buffer* bd;
662 
663  /*
664   * Set task control's passed to false to handle a timeout.
665   */
666  tc->passed = false;
667  passed = true;
668
669  for (i = 0; (i < 2) && passed; i++)
670  {
671    dev_t device = rtems_filesystem_make_dev_t (tc->major, tc->minor);
672
673    bdbuf_test_printf ("%s: rtems_bdbuf_get[0]: ", tc->name);
674    sc = rtems_bdbuf_get (device, 0, &bd);
675    if (!bdbuf_test_print_sc (sc, true))
676    {
677      passed = false;
678      break;
679    }
680       
681    bdbuf_test_printf ("%s: rtems_bdbuf_release[0]: ", tc->name);
682    sc = rtems_bdbuf_release (bd);
683    if (!bdbuf_test_print_sc (sc, true))
684    {
685      passed = false;
686      break;
687    }
688  }
689       
690  tc->passed = passed;
691  tc->test = 0;
692}
693
694/**
695 * Get the blocks 0 -> 4 and hold them. Wake the master to tell it was have the
696 * buffers then wait for the master to tell us to release a single buffer.
697 * Task 1 will be block waiting for each buffer. It is a higher priority.
698 */
699static void
700bdbuf_tests_task_0_test_2 (bdbuf_task_control* tc)
701{
702  rtems_status_code   sc;
703  bool                passed;
704  int                 i;
705  rtems_bdbuf_buffer* bd;
706  rtems_chain_control buffers;
707 
708  /*
709   * Set task control's passed to false to handle a timeout.
710   */
711  tc->passed = false;
712  passed = true;
713       
714  /*
715   * Get the blocks 0 -> 4 and hold them.
716   */
717  rtems_chain_initialize_empty (&buffers);
718       
719  for (i = 0; (i < 5) && passed; i++)
720  {
721    dev_t device = rtems_filesystem_make_dev_t (tc->major, tc->minor);
722
723    bdbuf_test_printf ("%s: rtems_bdbuf_get[%d]: ", tc->name, i);
724    sc = rtems_bdbuf_get (device, i, &bd);
725    if (!bdbuf_test_print_sc (sc, true))
726      passed = false;
727
728    rtems_chain_append (&buffers, &bd->link);
729  }
730
731  /*
732   * Wake the master to tell it we have the buffers.
733   */
734  bdbuf_send_wait_event (tc->name, "wake master", tc->master);
735               
736  if (passed)
737  {
738    /*
739     * For each buffer we hold wait until the master wakes us
740     * and then return it. Task 2 will block waiting for this
741     * buffer. It is a higher priority task.
742     */
743    for (i = 0; (i < 5) && passed; i++)
744    {
745      sc = bdbuf_wait (tc->name, BDBUF_SECONDS (5));
746      if (sc != RTEMS_SUCCESSFUL)
747      {
748        bdbuf_test_printf ("%s: wait failed: ", tc->name);
749        bdbuf_test_print_sc (sc, true);
750        passed = false;
751        break;
752      }
753      else
754      {
755        bdbuf_test_printf ("%s: rtems_bdbuf_release[%d]: unblocks task 1\n",
756                           tc->name, i);
757        bd = (rtems_bdbuf_buffer*) rtems_chain_get (&buffers);
758        sc = rtems_bdbuf_release (bd);
759        bdbuf_test_printf ("%s: rtems_bdbuf_release[%d]: ", tc->name, i);
760        if (!bdbuf_test_print_sc (sc, true))
761        {
762          passed = false;
763          break;
764        }
765      }
766    }
767  }
768       
769  tc->passed = passed;
770  tc->test = 0;
771}
772
773/**
774 * Read the block 5 from the disk modify it then release it modified.
775 */
776static void
777bdbuf_tests_task_0_test_3 (bdbuf_task_control* tc)
778{
779  rtems_status_code   sc;
780  bool                passed;
781  rtems_bdbuf_buffer* bd;
782  dev_t               device;
783 
784  /*
785   * Set task control's passed to false to handle a timeout.
786   */
787  tc->passed = false;
788  passed = true;
789
790  device = rtems_filesystem_make_dev_t (tc->major, tc->minor);
791
792  bdbuf_disk_lock (&bdbuf_disks[tc->minor]);
793  bdbuf_disks[tc->minor].driver_action = BDBUF_DISK_NOOP;
794  bdbuf_disk_unlock (&bdbuf_disks[tc->minor]);
795
796  /*
797   * Read the buffer and then release it.
798   */
799  bdbuf_test_printf ("%s: rtems_bdbuf_read[5]: ", tc->name);
800  sc = rtems_bdbuf_read (device, 5, &bd);
801  if ((passed = bdbuf_test_print_sc (sc, true)))
802  {
803    bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[5]: ", tc->name);
804    sc = rtems_bdbuf_release_modified (bd);
805    passed = bdbuf_test_print_sc (sc, true);
806  }
807
808  /*
809   * Read the buffer again and then just release. The buffer should
810   * be maintained as modified.
811   */
812  bdbuf_test_printf ("%s: rtems_bdbuf_read[5]: ", tc->name);
813  sc = rtems_bdbuf_read (device, 5, &bd);
814  if ((passed = bdbuf_test_print_sc (sc, true)))
815  {
816    bdbuf_test_printf ("%s: rtems_bdbuf_release[5]: ", tc->name);
817    sc = rtems_bdbuf_release (bd);
818    passed = bdbuf_test_print_sc (sc, true);
819  }
820
821  /*
822   * Set up a disk watch and wait for the write to happen.
823   */
824  bdbuf_set_disk_driver_watch (tc, 1);
825  passed = bdbuf_disk_driver_watch_wait (tc, BDBUF_SECONDS (5));
826
827  tc->passed = passed;
828  tc->test = 0;
829}
830
831static size_t
832bdbuf_test_buffer_count (void)
833{
834  return rtems_bdbuf_configuration.size / rtems_bdbuf_configuration.buffer_min;
835}
836
837/**
838 * Get all the blocks in the pool and hold them. Wake the master to tell it was
839 * have the buffers then wait for the master to tell us to release them.
840 */
841static void
842bdbuf_tests_task_0_test_4 (bdbuf_task_control* tc)
843{
844  rtems_status_code   sc;
845  bool                passed;
846  size_t              i;
847  rtems_bdbuf_buffer* bd;
848  rtems_chain_control buffers;
849  size_t              num = bdbuf_test_buffer_count ();
850 
851  /*
852   * Set task control's passed to false to handle a timeout.
853   */
854  tc->passed = false;
855  passed = true;
856       
857  /*
858   * Clear any disk settings.
859   */
860  bdbuf_clear_disk_driver_watch (tc);
861  bdbuf_set_disk_driver_action (tc, BDBUF_DISK_NOOP);
862 
863  /*
864   * Get the blocks 0 -> 4 and hold them.
865   */
866  rtems_chain_initialize_empty (&buffers);
867       
868  for (i = 0; (i < num) && passed; i++)
869  {
870    dev_t device = rtems_filesystem_make_dev_t (tc->major, tc->minor);
871
872    bdbuf_test_printf ("%s: rtems_bdbuf_read[%d]: ", tc->name, i);
873    sc = rtems_bdbuf_read (device, i, &bd);
874    if (!bdbuf_test_print_sc (sc, true))
875      passed = false;
876
877    rtems_chain_append (&buffers, &bd->link);
878  }
879
880  /*
881   * Wake the master to tell it we have the buffers.
882   */
883  bdbuf_send_wait_event (tc->name, "wake master", tc->master);
884               
885  if (passed)
886  {
887    bdbuf_sleep (250);
888
889    bdbuf_set_disk_driver_watch (tc, num / 2);
890
891    /*
892     * Release half the buffers, wait 500msecs then release the
893     * remainder. This tests the swap out timer on each buffer.
894     */
895    bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[0]: unblocks task 1\n",
896                       tc->name);   
897    bd = (rtems_bdbuf_buffer*) rtems_chain_get (&buffers);
898    sc = rtems_bdbuf_release_modified (bd);
899    bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[0]: ", tc->name);
900    passed = bdbuf_test_print_sc (sc, true);
901    if (passed)
902    {
903      for (i = 1; (i < (num / 2)) && passed; i++)
904      {
905        bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[%d]: " \
906                           "unblocks task 1\n", tc->name, i);
907        bd = (rtems_bdbuf_buffer*) rtems_chain_get (&buffers);
908        sc = rtems_bdbuf_release_modified (bd);
909        bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[%d]: ",
910                           tc->name, i);
911        passed = bdbuf_test_print_sc (sc, true);
912        if (!passed)
913          break;
914      }
915
916      if (passed)
917      {
918        passed = bdbuf_disk_driver_watch_wait (tc, BDBUF_SECONDS (5));
919
920        if (passed)
921        {
922          bdbuf_sleep (500);
923
924          bdbuf_set_disk_driver_watch (tc, num / 2);
925       
926          for (i = 0; (i < (num / 2)) && passed; i++)
927          {
928            bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[%d]: ",
929                               tc->name, i + (num / 2));
930            bd = (rtems_bdbuf_buffer*) rtems_chain_get (&buffers);
931            passed = bdbuf_test_print_sc (rtems_bdbuf_release_modified (bd),
932                                          true);
933            if (!passed)
934              break;
935          }
936
937          passed = bdbuf_disk_driver_watch_wait (tc, BDBUF_SECONDS (5));
938
939          if (passed)
940          {
941            if (!rtems_chain_is_empty (&buffers))
942            {
943              passed = false;
944              bdbuf_test_printf ("%s: buffer chain not empty\n", tc->name);
945            }
946          }
947        }
948      }
949    }
950  }
951       
952  tc->passed = passed;
953  tc->test = 0;
954}
955
956static void
957bdbuf_tests_task_0_test_5 (bdbuf_task_control* tc)
958{
959  bdbuf_tests_task_0_test_4 (tc);
960}
961
962static void
963bdbuf_tests_task_0_test_6 (bdbuf_task_control* tc)
964{
965  rtems_status_code   sc;
966  bool                passed;
967  int                 i;
968  rtems_bdbuf_buffer* bd;
969  rtems_chain_control buffers;
970 
971  /*
972   * Set task control's passed to false to handle a timeout.
973   */
974  tc->passed = false;
975  passed = true;
976       
977  /*
978   * Clear any disk settings.
979   */
980  bdbuf_clear_disk_driver_watch (tc);
981  bdbuf_set_disk_driver_action (tc, BDBUF_DISK_NOOP);
982 
983  /*
984   * Get the blocks 0 -> 4 and hold them.
985   */
986  rtems_chain_initialize_empty (&buffers);
987       
988  for (i = 0; (i < 5) && passed; i++)
989  {
990    dev_t device = rtems_filesystem_make_dev_t (tc->major, tc->minor);
991
992    bdbuf_test_printf ("%s: rtems_bdbuf_read[%d]: ", tc->name, i);
993    sc = rtems_bdbuf_get (device, i, &bd);
994    if (!bdbuf_test_print_sc (sc, true))
995      passed = false;
996
997    rtems_chain_append (&buffers, &bd->link);
998  }
999
1000  for (i = 0; (i < 4) && passed; i++)
1001  {
1002    bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[%d]: ",
1003                       tc->name, i);
1004    bd = (rtems_bdbuf_buffer*) rtems_chain_get (&buffers);
1005    passed = bdbuf_test_print_sc (rtems_bdbuf_release_modified (bd),
1006                                  true);
1007  }
1008
1009  if (passed)
1010  {
1011    bdbuf_test_printf ("%s: rtems_bdbuf_sync[%d]: ", tc->name, i);
1012    bd = (rtems_bdbuf_buffer*) rtems_chain_get (&buffers);
1013
1014    passed = bdbuf_test_print_sc (rtems_bdbuf_sync (bd), true);
1015  }
1016       
1017  tc->passed = passed;
1018  tc->test = 0;
1019}
1020
1021static void
1022bdbuf_tests_task_0_test_7 (bdbuf_task_control* tc)
1023{
1024  rtems_status_code   sc;
1025  bool                passed;
1026  int                 i;
1027  rtems_bdbuf_buffer* bd;
1028  rtems_chain_control buffers;
1029  dev_t               device;
1030 
1031  /*
1032   * Set task control's passed to false to handle a timeout.
1033   */
1034  tc->passed = false;
1035  passed = true;
1036       
1037  /*
1038   * Clear any disk settings.
1039   */
1040  bdbuf_clear_disk_driver_watch (tc);
1041  bdbuf_set_disk_driver_action (tc, BDBUF_DISK_NOOP);
1042
1043  device = rtems_filesystem_make_dev_t (tc->major, tc->minor);
1044 
1045  /*
1046   * Get the blocks 0 -> 4 and hold them.
1047   */
1048  rtems_chain_initialize_empty (&buffers);
1049       
1050  for (i = 0; (i < 5) && passed; i++)
1051  {
1052    bdbuf_test_printf ("%s: rtems_bdbuf_read[%d]: ", tc->name, i);
1053    sc = rtems_bdbuf_get (device, i, &bd);
1054    if (!bdbuf_test_print_sc (sc, true))
1055      passed = false;
1056
1057    rtems_chain_append (&buffers, &bd->link);
1058  }
1059
1060  for (i = 0; (i < 5) && passed; i++)
1061  {
1062    bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[%d]: ",
1063                       tc->name, i);
1064    bd = (rtems_bdbuf_buffer*) rtems_chain_get (&buffers);
1065    passed = bdbuf_test_print_sc (rtems_bdbuf_release_modified (bd),
1066                                  true);
1067  }
1068
1069  if (passed)
1070  {
1071    bdbuf_test_printf ("%s: rtems_bdbuf_syncdev[%d:%d]: ",
1072                       tc->name, i,
1073                       rtems_filesystem_dev_major_t (device),
1074                       rtems_filesystem_dev_minor_t (device));
1075    passed = bdbuf_test_print_sc (rtems_bdbuf_syncdev (device), true);
1076  }
1077       
1078  tc->passed = passed;
1079  tc->test = 0;
1080}
1081
1082static void
1083bdbuf_tests_task_0_test_8 (bdbuf_task_control* tc)
1084{
1085  rtems_status_code   sc;
1086  bool                passed;
1087  int                 i;
1088  rtems_bdbuf_buffer* bd;
1089  rtems_chain_control buffers;
1090  rtems_chain_node*   node;
1091  rtems_chain_node*   pnode;
1092  dev_t               device;
1093 
1094  /*
1095   * Set task control's passed to false to handle a timeout.
1096   */
1097  tc->passed = false;
1098  passed = true;
1099       
1100  /*
1101   * Clear any disk settings.
1102   */
1103  bdbuf_clear_disk_driver_watch (tc);
1104  bdbuf_set_disk_driver_action (tc, BDBUF_DISK_NOOP);
1105
1106  device = rtems_filesystem_make_dev_t (tc->major, tc->minor);
1107 
1108  /*
1109   * Get the blocks 0 -> 4 and hold them.
1110   */
1111  rtems_chain_initialize_empty (&buffers);
1112       
1113  for (i = 0; (i < 5) && passed; i++)
1114  {
1115    bdbuf_test_printf ("%s: rtems_bdbuf_read[%d]: ", tc->name, i);
1116    sc = rtems_bdbuf_get (device, i, &bd);
1117    if (!bdbuf_test_print_sc (sc, true))
1118      passed = false;
1119
1120    rtems_chain_append (&buffers, &bd->link);
1121  }
1122
1123  node = rtems_chain_tail (&buffers);
1124  node = node->previous;
1125
1126  bd = (rtems_bdbuf_buffer*) node;
1127  pnode = node->previous;
1128  rtems_chain_extract (node);
1129  node = pnode;
1130  bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[4]: ", tc->name);
1131  passed = bdbuf_test_print_sc (rtems_bdbuf_release_modified (bd), true);
1132
1133  bd = (rtems_bdbuf_buffer*) node;
1134  pnode = node->previous;
1135  rtems_chain_extract (node);
1136  node = pnode;
1137  bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[3]: ", tc->name);
1138  passed = bdbuf_test_print_sc (rtems_bdbuf_release_modified (bd), true);
1139
1140  for (i = 0; (i < 3) && passed; i++)
1141  {
1142    bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[%d]: ",
1143                       tc->name, i);
1144    bd = (rtems_bdbuf_buffer*) rtems_chain_get (&buffers);
1145    passed = bdbuf_test_print_sc (rtems_bdbuf_release_modified (bd),
1146                                  true);
1147  }
1148
1149  if (passed)
1150  {
1151    /*
1152     * Check the block order.
1153     */
1154    bdbuf_set_disk_driver_action (tc, BDBUF_DISK_BLOCKS_INORDER);
1155   
1156    bdbuf_test_printf ("%s: rtems_bdbuf_syncdev[%d:%d]: checking order\n",
1157                       tc->name, i,
1158                       rtems_filesystem_dev_major_t (device),
1159                       rtems_filesystem_dev_minor_t (device));
1160    sc = rtems_bdbuf_syncdev (device);
1161    bdbuf_test_printf ("%s: rtems_bdbuf_syncdev[%d:%d]: ",
1162                       tc->name, i,
1163                       rtems_filesystem_dev_major_t (device),
1164                       rtems_filesystem_dev_minor_t (device));
1165    passed = bdbuf_test_print_sc (sc, true);
1166  }
1167
1168  tc->passed = passed;
1169  tc->test = 0;
1170}
1171
1172static void
1173bdbuf_tests_task_0 (rtems_task_argument arg)
1174{
1175  bdbuf_task_control* tc = (bdbuf_task_control*) arg;
1176 
1177  while (!tc->die)
1178  {
1179    switch (tc->test)
1180    {
1181      case 0:
1182        /*
1183         * Wait for the next test.
1184         */
1185        bdbuf_wait (tc->name, 0);
1186        break;
1187
1188      case 1:
1189        bdbuf_tests_task_0_test_1 (tc);
1190        break;
1191       
1192      case 2:
1193        bdbuf_tests_task_0_test_2 (tc);
1194        break;
1195
1196      case 3:
1197        bdbuf_tests_task_0_test_3 (tc);
1198        break;
1199
1200      case 4:
1201        bdbuf_tests_task_0_test_4 (tc);
1202        break;
1203
1204      case 5:
1205        bdbuf_tests_task_0_test_5 (tc);
1206        break;
1207
1208      case 6:
1209        bdbuf_tests_task_0_test_6 (tc);
1210        break;
1211
1212      case 7:
1213        bdbuf_tests_task_0_test_7 (tc);
1214        break;
1215
1216      case 8:
1217        bdbuf_tests_task_0_test_8 (tc);
1218        break;
1219
1220      default:
1221        /*
1222         * Invalid test for this task. An error.
1223         */
1224        bdbuf_test_printf ("%s: invalid test: %d\n", tc->name, tc->test);
1225        tc->passed = false;
1226        tc->test = 0;
1227        break;
1228    }
1229  }
1230
1231  bdbuf_test_printf ("%s: delete task\n", tc->name);
1232  rtems_task_delete (RTEMS_SELF);
1233}
1234
1235/**
1236 * Get the blocks 0 -> 4 and release them. Task 0 should be holding
1237 * each one.
1238 */
1239static void
1240bdbuf_tests_ranged_get_release (bdbuf_task_control* tc,
1241                                bool                wake_master,
1242                                int                 lower,
1243                                int                 upper)
1244{
1245  rtems_status_code   sc;
1246  bool                passed;
1247  int                 i;
1248  rtems_bdbuf_buffer* bd;
1249 
1250  /*
1251   * Set task control's passed to false to handle a timeout.
1252   */
1253  tc->passed = false;
1254  passed = true;
1255
1256  for (i = lower; (i < upper) && passed; i++)
1257  {
1258    dev_t device = rtems_filesystem_make_dev_t (tc->major, tc->minor);
1259   
1260    bdbuf_test_printf ("%s: rtems_bdbuf_get[%d]: blocking ...\n", tc->name, i);
1261    sc = rtems_bdbuf_get (device, i, &bd);
1262    bdbuf_test_printf ("%s: rtems_bdbuf_get[%d]: ", tc->name, i);
1263    if (!bdbuf_test_print_sc (sc, true))
1264    {
1265      passed = false;
1266      break;
1267    }
1268
1269    bdbuf_test_printf ("%s: rtems_bdbuf_release[%d]: ", tc->name, i);
1270    sc = rtems_bdbuf_release (bd);
1271    if (!bdbuf_test_print_sc (sc, true))
1272    {
1273      passed = false;
1274      break;
1275    }
1276
1277    /*
1278     * Wake the master to tell it we have finished.
1279     */
1280    if (wake_master)
1281      bdbuf_send_wait_event (tc->name, "wake master", tc->master);
1282  }
1283       
1284  tc->passed = passed;
1285  tc->test = 0;
1286}
1287
1288static void
1289bdbuf_tests_task_1 (rtems_task_argument arg)
1290{
1291  bdbuf_task_control* tc = (bdbuf_task_control*) arg;
1292
1293  while (!tc->die)
1294  {
1295    switch (tc->test)
1296    {
1297      case 0:
1298        /*
1299         * Wait for the next test.
1300         */
1301        bdbuf_wait (tc->name, 0);
1302        break;
1303
1304      case 2:
1305        bdbuf_tests_ranged_get_release (tc, false, 0, 5);
1306        break;
1307
1308      case 4:
1309        bdbuf_tests_ranged_get_release (tc, false, 0, 9);
1310        break;
1311
1312      case 5:
1313        bdbuf_tests_ranged_get_release (tc, false, 20, 25);
1314        break;
1315
1316      default:
1317        /*
1318         * Invalid test for this task. An error.
1319         */
1320        bdbuf_test_printf ("%s: invalid test: %d\n", tc->name, tc->test);
1321        tc->passed = false;
1322        tc->test = 0;
1323        break;
1324    }
1325  }
1326
1327  bdbuf_test_printf ("%s: delete task\n", tc->name);
1328  rtems_task_delete (RTEMS_SELF);
1329}
1330
1331/**
1332 * Get the blocks 0 -> 4 and release them. Task 0 should be holding
1333 * each one.
1334 */
1335static void
1336bdbuf_tests_task_2_test_2 (bdbuf_task_control* tc)
1337{
1338  /*
1339   * Use task 1's test 2. They are the same.
1340   */
1341  bdbuf_tests_ranged_get_release (tc, true, 0, 5);
1342}
1343
1344static void
1345bdbuf_tests_task_2 (rtems_task_argument arg)
1346{
1347  bdbuf_task_control* tc = (bdbuf_task_control*) arg;
1348 
1349  while (!tc->die)
1350  {
1351    switch (tc->test)
1352    {
1353      case 0:
1354        /*
1355         * Wait for the next test.
1356         */
1357        bdbuf_wait (tc->name, 0);
1358        break;
1359
1360      case 2:
1361        bdbuf_tests_task_2_test_2 (tc);
1362        break;
1363
1364      default:
1365        /*
1366         * Invalid test for this task. An error.
1367         */
1368        bdbuf_test_printf ("%s: invalid test: %d\n", tc->name, tc->test);
1369        tc->passed = false;
1370        tc->test = 0;
1371        break;
1372    }
1373  }
1374
1375  bdbuf_test_printf ("%s: delete task\n", tc->name);
1376  rtems_task_delete (RTEMS_SELF);
1377}
1378
1379/**
1380 * Table of task entry points.
1381 */
1382static rtems_task_entry bdbuf_test_tasks[] =
1383{
1384  bdbuf_tests_task_0,
1385  bdbuf_tests_task_1,
1386  bdbuf_tests_task_2
1387};
1388 
1389#define BDBUF_TESTS_PRI_HIGH (30)
1390
1391/**
1392 * Wait for the all tests to finish. This is signalled by the test
1393 * number becoming 0.
1394 */
1395static bool
1396bdbuf_tests_finished (bdbuf_task_control* tasks)
1397{
1398  uint32_t time = 0;
1399  bool     finished = false;
1400
1401  while (time < (10 * 4))
1402  {
1403    int t;
1404
1405    finished = true;
1406   
1407    for (t = 0; t < BDBUF_TEST_TASKS; t++)
1408      if (tasks[t].test)
1409      {
1410        finished = false;
1411        break;
1412      }
1413
1414    if (finished)
1415      break;
1416   
1417    bdbuf_sleep (250);
1418    time++;
1419  }
1420
1421  if (!finished)
1422    bdbuf_test_printf ("master: test timed out\n");
1423  else
1424  {
1425    int t;
1426    for (t = 0; t < BDBUF_TEST_TASKS; t++)
1427      if (!tasks[0].passed)
1428      {
1429        finished = false;
1430        break;
1431      }
1432  }
1433 
1434  return finished;
1435}
1436
1437/**
1438 * Test 1.
1439 *
1440 * # Get task 0 to get buffer 0 from the pool then release it twice.
1441 */
1442static bool
1443bdbuf_test_1 (bdbuf_task_control* tasks)
1444{
1445  tasks[0].test = 1;
1446
1447  /*
1448   * Use pool 0.
1449   */ 
1450  tasks[0].minor = 0;
1451 
1452  bdbuf_send_wait_event ("master", "wake task 0", tasks[0].task);
1453
1454  return bdbuf_tests_finished (tasks);
1455}
1456
1457/**
1458 * Test 2.
1459 *
1460 * # Get task 0 to get buffers 0 -> 4 from the pool hold them. Then get
1461 * task 1 and task 2 to get them with blocking. The 2 tasks tests the
1462 * priority blocking on the buffer.
1463 */
1464static bool
1465bdbuf_test_2 (bdbuf_task_control* tasks)
1466{
1467  int i;
1468 
1469  tasks[0].test = 2;
1470  tasks[1].test = 2;
1471  tasks[2].test = 2;
1472
1473  /*
1474   * Use pool 0.
1475   */
1476  tasks[0].minor = 0;
1477  tasks[1].minor = 0;
1478  tasks[2].minor = 0;
1479
1480  /*
1481   * Wake task 0 and wait for it to have all the buffers.
1482   */
1483  bdbuf_send_wait_event ("master", "wake task 0", tasks[0].task);
1484  if (bdbuf_wait ("master", BDBUF_SECONDS (5)) != RTEMS_SUCCESSFUL)
1485    return false;
1486
1487  /*
1488   * Wake task 1.
1489   */
1490  bdbuf_send_wait_event ("master", "wake task 1", tasks[1].task);
1491
1492  /*
1493   * Wake task 2.
1494   */
1495  bdbuf_send_wait_event ("master", "wake task 2", tasks[2].task);
1496 
1497  for (i = 0; i < 5; i++)
1498  {
1499    /*
1500     * Wake task 0 and watch task 2 then task 1 get the released buffer.
1501     */
1502    bdbuf_send_wait_event ("master", "wake task 0", tasks[0].task);
1503   
1504    /*
1505     * Wait until task 2 has the buffer.
1506     */
1507    if (bdbuf_wait ("master", BDBUF_SECONDS (5)) != RTEMS_SUCCESSFUL)
1508      return false;
1509  }
1510 
1511  /*
1512   * Wait for the tests to finish.
1513   */
1514  return bdbuf_tests_finished (tasks);
1515}
1516
1517/**
1518 * Test 3.
1519 *
1520 * # Read a block from disk into the buffer, modify the block and release
1521 * it modified. Use a block great then 4 because 0 -> 4 are in the cache.
1522 */
1523static bool
1524bdbuf_test_3 (bdbuf_task_control* tasks)
1525{
1526  tasks[0].test = 3;
1527
1528  /*
1529   * Use pool 0.
1530   */
1531  tasks[0].minor = 0;
1532
1533  /*
1534   * Wake task 0.
1535   */
1536  bdbuf_send_wait_event ("master", "wake task 0", tasks[0].task);
1537 
1538  return bdbuf_tests_finished (tasks);
1539}
1540
1541/**
1542 * Test 4.
1543 *
1544 * # Read every buffer in the pool and hold. Then get task 1 to ask for another
1545 *   buffer that is being accessed. It will block waiting for it to appear.
1546 */
1547static bool
1548bdbuf_test_4 (bdbuf_task_control* tasks)
1549{
1550  tasks[0].test = 4;
1551  tasks[1].test = 4;
1552
1553  /*
1554   * Use pool 0.
1555   */
1556  tasks[0].minor = 0;
1557  tasks[1].minor = 0;
1558
1559  /*
1560   * Wake task 0.
1561   */
1562  bdbuf_send_wait_event ("master", "wake task 0", tasks[0].task);
1563
1564  /*
1565   * Wait for the buffers in the pool to be taken.
1566   */
1567  if (bdbuf_wait ("master", BDBUF_SECONDS (5)) != RTEMS_SUCCESSFUL)
1568    return false;
1569
1570  bdbuf_sleep (100);
1571
1572  /*
1573   * Wake task 1 to read another one and have to block.
1574   */
1575  bdbuf_send_wait_event ("master", "wake task 1", tasks[1].task);
1576
1577  bdbuf_sleep (100);
1578
1579  /*
1580   * Wake task 0 to release it buffers.
1581   */
1582  bdbuf_send_wait_event ("master", "wake task 0", tasks[0].task);
1583 
1584  return bdbuf_tests_finished (tasks);
1585}
1586
1587/**
1588 * Test 5.
1589 *
1590 * # Read every buffer in the pool and hold. Then get task 1 to ask for a new
1591 *   buffer. It will block waiting for one to appear.
1592 */
1593static bool
1594bdbuf_test_5 (bdbuf_task_control* tasks)
1595{
1596  tasks[0].test = 5;
1597  tasks[1].test = 5;
1598
1599  /*
1600   * Use pool 0.
1601   */
1602  tasks[0].minor = 0;
1603  tasks[1].minor = 0;
1604
1605  /*
1606   * Wake task 0.
1607   */
1608  bdbuf_send_wait_event ("master", "wake task 0", tasks[0].task);
1609
1610  /*
1611   * Wait for the buffers in the pool to be taken.
1612   */
1613  if (bdbuf_wait ("master", BDBUF_SECONDS (5)) != RTEMS_SUCCESSFUL)
1614    return false;
1615
1616  bdbuf_sleep (100);
1617
1618  /*
1619   * Wake task 1 to read another one and have to block.
1620   */
1621  bdbuf_send_wait_event ("master", "wake task 1", tasks[1].task);
1622
1623  bdbuf_sleep (100);
1624
1625  /*
1626   * Wake task 0 to release it buffers.
1627   */
1628  bdbuf_send_wait_event ("master", "wake task 0", tasks[0].task);
1629 
1630  return bdbuf_tests_finished (tasks);
1631}
1632
1633/**
1634 * Test 6.
1635 *
1636 * # Get 5 buffers, release modify 4 then sync the last.
1637 */
1638static bool
1639bdbuf_test_6 (bdbuf_task_control* tasks)
1640{
1641  tasks[0].test = 6;
1642
1643  /*
1644   * Use pool 0.
1645   */
1646  tasks[0].minor = 0;
1647
1648  /*
1649   * Wake task 0.
1650   */
1651  bdbuf_send_wait_event ("master", "wake task 0", tasks[0].task);
1652
1653  return bdbuf_tests_finished (tasks);
1654}
1655
1656/**
1657 * Test 7.
1658 *
1659 * # Get 5 buffers, release modify them all then sync the device.
1660 */
1661static bool
1662bdbuf_test_7 (bdbuf_task_control* tasks)
1663{
1664  tasks[0].test = 7;
1665
1666  /*
1667   * Use pool 0.
1668   */
1669  tasks[0].minor = 0;
1670
1671  /*
1672   * Wake task 0.
1673   */
1674  bdbuf_send_wait_event ("master", "wake task 0", tasks[0].task);
1675
1676  return bdbuf_tests_finished (tasks);
1677}
1678
1679/**
1680 * Test 8.
1681 *
1682 * # Get 5 buffers, release modify the last 2 then the reset from 0.
1683 */
1684static bool
1685bdbuf_test_8 (bdbuf_task_control* tasks)
1686{
1687  tasks[0].test = 8;
1688
1689  /*
1690   * Use pool 0.
1691   */
1692  tasks[0].minor = 0;
1693
1694  /*
1695   * Wake task 0.
1696   */
1697  bdbuf_send_wait_event ("master", "wake task 0", tasks[0].task);
1698
1699  return bdbuf_tests_finished (tasks);
1700}
1701
1702/**
1703 * A test.
1704 */
1705typedef bool (*bdbuf_test) (bdbuf_task_control* tasks);
1706
1707/**
1708 * A test name and function.
1709 */
1710typedef struct bdbuf_test_ident
1711{
1712  const char* label;
1713  bdbuf_test  test;
1714} bdbuf_test_ident;
1715 
1716/**
1717 * Table of tests.
1718 */
1719static bdbuf_test_ident bdbuf_tests[] =
1720{
1721  {
1722    "Task 0 get buffer 0 from pool 0",
1723    bdbuf_test_1
1724  },
1725  {
1726    "Task 0 get buffer 0 -> 4 from pool 0, task 2 and 1 block getting",
1727    bdbuf_test_2
1728  },
1729  {
1730    "Task 0 read buffer 5, modify and release modified",
1731    bdbuf_test_3
1732  },
1733  {
1734    "Task 0 read all buffers, task 1 blocks waiting for acessed buffer",
1735    bdbuf_test_4
1736  },
1737  {
1738    "Task 0 read all buffers, task 1 blocks waiting for new buffer",
1739    bdbuf_test_5
1740  },
1741  {
1742    "Task 0 release modified 4 buffers then syncs a 5th buffer",
1743    bdbuf_test_6
1744  },
1745  {
1746    "Task 0 release modified 5 buffers then sync the device",
1747    bdbuf_test_7
1748  },
1749  {
1750    "Task 0 releases modified 5 buffers is out or order sequence and the" \
1751    " driver checks the buffers are in order",
1752    bdbuf_test_8
1753  }
1754};
1755
1756#define BDBUF_TEST_NUM (sizeof (bdbuf_tests) / sizeof (bdbuf_test_ident))
1757
1758/**
1759 * Test the BD Buffering code.
1760 */
1761static void
1762bdbuf_tester (void)
1763{
1764  rtems_device_major_number major;
1765  bdbuf_task_control        tasks[BDBUF_TEST_TASKS];
1766  rtems_task_priority       old_priority;
1767  int                       t;
1768  bool                      passed = true;
1769
1770  /*
1771   * Change priority to a lower one.
1772   */
1773  bdbuf_test_printf ("lower priority to %d: ", BDBUF_TESTS_PRI_HIGH + 1);
1774  bdbuf_test_print_sc (rtems_task_set_priority (RTEMS_SELF,
1775                                                BDBUF_TESTS_PRI_HIGH + 1,
1776                                                &old_priority),
1777                       true);
1778 
1779  /*
1780   * This sets up the buffer pools.
1781   */
1782  if (!bdbuf_tests_setup_disk (&major))
1783  {
1784    bdbuf_test_printf ("disk set up failed\n");
1785    return;
1786  }
1787
1788  /*
1789   * Make sure the swapout task has run. The user could block
1790   * the swapout task from running until later. This is not
1791   * tested.
1792   */
1793  bdbuf_sleep (100);
1794
1795  /*
1796   * Start the test tasks used to test the threading parts
1797   * of the bdbuf code.
1798   */ 
1799  for (t = 0; t < BDBUF_TEST_TASKS; t++)
1800  {
1801    bdbuf_task_control_init (t, &tasks[t],
1802                             rtems_task_self (),
1803                             major);
1804 
1805    if (!bdbuf_tests_create_task (&tasks[t],
1806                                  BDBUF_TESTS_PRI_HIGH - t,
1807                                  bdbuf_test_tasks[t]))
1808    return;
1809  }
1810
1811  /*
1812   * Let the test tasks run if they have not already done so.
1813   */
1814  bdbuf_sleep (100);
1815
1816  /*
1817   * Perform each test.
1818   */
1819  for (t = 0; (t < BDBUF_TEST_NUM) && passed; t++)
1820  {
1821    bdbuf_test_printf ("test %d: %s\n", t + 1, bdbuf_tests[t].label);
1822    passed = bdbuf_tests[t].test (tasks);
1823    bdbuf_test_printf ("test %d: %s\n", t + 1, passed ? "passed" : "failed");
1824  }
1825}
1826
1827static rtems_task Init(rtems_task_argument argument)
1828{
1829  printf ("\n\n*** TEST BLOCK 6 ***\n");
1830
1831  bdbuf_tester ();
1832
1833  printf ("*** END OF TEST BLOCK 6 ***\n");
1834
1835  exit (0);
1836}
1837
1838#define CONFIGURE_INIT
1839
1840#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
1841#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
1842#define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK
1843
1844#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
1845
1846#define CONFIGURE_MAXIMUM_TASKS 8
1847#define CONFIGURE_MAXIMUM_DRIVERS 3
1848#define CONFIGURE_MAXIMUM_SEMAPHORES 7
1849
1850#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
1851
1852#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.