source: rtems/testsuites/libtests/block06/init.c @ 36d974ba

5
Last change on this file since 36d974ba was 36d974ba, checked in by Chris Johns <chrisj@…>, on 10/22/17 at 22:57:52

testsuite: Remove warnings.

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