source: rtems/testsuites/libtests/block06/init.c @ 51b3cbca

5
Last change on this file since 51b3cbca was 51b3cbca, checked in by Sebastian Huber <sebastian.huber@…>, on 10/04/18 at 13:23:25

tests: Use rtems_task_exit()

Update #3533.

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