source: rtems/testsuites/libtests/block06/init.c @ 4ee0fa87

4.115
Last change on this file since 4ee0fa87 was 4ee0fa87, checked in by Sebastian Huber <sebastian.huber@…>, on 03/26/12 at 10:54:36

libtests/block06: Increase stack size

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