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

5
Last change on this file since af43554 was af43554, checked in by Sebastian Huber <sebastian.huber@…>, on 10/26/17 at 11:59:11

tests: Remove TEST_INIT

The TEST_EXTERN is a used only by the system.h style tests and they use
CONFIGURE_INIT appropriately.

Update #3170.
Update #3199.

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