source: rtems/testsuites/libtests/block06/init.c @ 24d0ee57

5
Last change on this file since 24d0ee57 was 24d0ee57, checked in by Chris Johns <chrisj@…>, on 05/20/16 at 08:39:50

cpukit, testsuite: Add rtems_printf and rtems_printer support.

This change adds rtems_printf and related functions and wraps the
RTEMS print plugin support into a user API. All references to the
plugin are removed and replaced with the rtems_printer interface.

Printk and related functions are made to return a valid number of
characters formatted and output.

The function attribute to check printf functions has been added
to rtems_printf and printk. No changes to remove warrnings are part
of this patch set.

The testsuite has been moved over to the rtems_printer. The testsuite
has a mix of rtems_printer access and direct print control via the
tmacros.h header file. The support for begink/endk has been removed
as it served no purpose and only confused the code base. The testsuite
has not been refactored to use rtems_printf. This is future work.

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