source: rtems/testsuites/libtests/block06/init.c @ 7660e8b3

4.115
Last change on this file since 7660e8b3 was 7660e8b3, checked in by Sebastian Huber <sebastian.huber@…>, on 07/23/13 at 11:32:58

Include missing <string.h>

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