L4Re/departure

Annotated tests/dstest_pipe_client.cc

164:aa09cdd2a3bf
2021-08-05 Paul Boddie Removed the superfluous flush operation and fixed pipe numbering in messages.
paul@65 1
/*
paul@65 2
 * Test pipe operations.
paul@65 3
 *
paul@65 4
 * Copyright (C) 2020, 2021 Paul Boddie <paul@boddie.org.uk>
paul@65 5
 *
paul@65 6
 * This program is free software; you can redistribute it and/or
paul@65 7
 * modify it under the terms of the GNU General Public License as
paul@65 8
 * published by the Free Software Foundation; either version 2 of
paul@65 9
 * the License, or (at your option) any later version.
paul@65 10
 *
paul@65 11
 * This program is distributed in the hope that it will be useful,
paul@65 12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
paul@65 13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
paul@65 14
 * GNU General Public License for more details.
paul@65 15
 *
paul@65 16
 * You should have received a copy of the GNU General Public License
paul@65 17
 * along with this program; if not, write to the Free Software
paul@65 18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
paul@65 19
 * Boston, MA  02110-1301, USA
paul@65 20
 */
paul@65 21
paul@65 22
#include <l4/re/env.h>
paul@65 23
#include <l4/sys/err.h>
paul@65 24
paul@117 25
#include <thread>
paul@117 26
paul@65 27
#include <stdio.h>
paul@65 28
#include <string.h>
paul@65 29
#include <stdlib.h>
paul@123 30
#include <unistd.h> /* sleep */
paul@65 31
paul@108 32
#include <fsclient/client.h>
paul@65 33
paul@65 34
paul@66 35
paul@117 36
/* Use the writer to fill the pipe with data. */
paul@117 37
paul@124 38
static void write_pipe(file_t *writer, int number)
paul@117 39
{
paul@117 40
  offset_t size = 600;
paul@117 41
  char buffer[size];
paul@124 42
  long err;
paul@124 43
paul@124 44
  /* Make writers blocking to permit synchronisation. */
paul@124 45
paul@124 46
  if ((err = client_set_blocking(writer, NOTIFY_SPACE_AVAILABLE)))
paul@124 47
  {
paul@124 48
    printf("Could not set pipe #%d as blocking: %s\n", number, l4sys_errtostr(err));
paul@124 49
    return;
paul@124 50
  }
paul@117 51
paul@117 52
  for (int loop = 0; loop < 3; loop++)
paul@117 53
  {
paul@117 54
    for (int region = 0; region < 26; region++)
paul@117 55
    {
paul@117 56
      memset(buffer, (int) 'a' + region, size);
paul@117 57
paul@117 58
      offset_t nwritten = client_write(writer, buffer, size);
paul@117 59
paul@124 60
      printf("Written %ld/%ld in #%d of %d/%d to pipe #%d...\n", nwritten, size, region, loop, 2, number);
paul@117 61
    }
paul@123 62
paul@123 63
    sleep(1);
paul@117 64
  }
paul@117 65
paul@117 66
  /* Flush to make the final output available. */
paul@117 67
paul@132 68
  client_close(writer);
paul@117 69
}
paul@117 70
paul@117 71
/* Use the reader to obtain data from the pipe. */
paul@117 72
paul@123 73
static void read_pipes(file_t *reader1, file_t *reader2)
paul@117 74
{
paul@123 75
  offset_t size = 600, totals[] = {0, 0};
paul@126 76
  unsigned int active = 2;
paul@124 77
  long err;
paul@123 78
  file_t *reader;
paul@124 79
paul@124 80
  /* Register the readers for notification. */
paul@124 81
paul@124 82
  if ((err = client_subscribe(reader1, NOTIFY_CONTENT_AVAILABLE | NOTIFY_PEER_CLOSED)) ||
paul@124 83
      (err = client_subscribe(reader2, NOTIFY_CONTENT_AVAILABLE | NOTIFY_PEER_CLOSED)))
paul@123 84
  {
paul@124 85
    printf("Could not subscribe to notifications: %s\n", l4sys_errtostr(err));
paul@123 86
    return;
paul@123 87
  }
paul@123 88
paul@123 89
  while (1)
paul@117 90
  {
paul@124 91
    char buffer[size];
paul@124 92
    offset_t nread;
paul@124 93
paul@123 94
    /* Wait for notification of content. */
paul@123 95
paul@124 96
    err = client_wait_files(&reader);
paul@123 97
paul@123 98
    if (err)
paul@123 99
    {
paul@123 100
      printf("Error waiting for notifications: %s\n", l4sys_errtostr(err));
paul@123 101
      return;
paul@123 102
    }
paul@123 103
paul@123 104
    if ((reader != reader1) && (reader != reader2))
paul@123 105
    {
paul@123 106
      printf("Spurious notification received for %p versus %p, %p.\n", reader, reader1, reader2);
paul@123 107
      continue;
paul@123 108
    }
paul@123 109
paul@123 110
    int p = reader == reader1 ? 0 : 1;
paul@123 111
paul@164 112
    printf("Pipe #%d notified with conditions:%s%s\n", p + 1, reader->notifications & NOTIFY_PEER_CLOSED ? " closed" : "",
paul@164 113
                                                              reader->notifications & NOTIFY_CONTENT_AVAILABLE ? " content" : "");
paul@126 114
paul@126 115
    nread = client_read(reader, buffer, size);
paul@123 116
paul@124 117
    while (nread)
paul@123 118
    {
paul@123 119
      totals[p] += nread;
paul@123 120
paul@124 121
      printf("Read %ld/%ld, total %ld, first %c, last %c, from pipe #%d...\n", nread, size, totals[p], *buffer, *(buffer + nread - 1), p + 1);
paul@123 122
#if 0
paul@123 123
      for (offset_t i = 0; i < nread; i += 60)
paul@123 124
      {
paul@123 125
        fwrite(buffer + i, sizeof(char), nread - i > 60 ? 60 : nread - i, stdout);
paul@123 126
        fputs("\n", stdout);
paul@123 127
      }
paul@123 128
#endif
paul@123 129
      nread = client_read(reader, buffer, size);
paul@123 130
    }
paul@128 131
paul@128 132
    /* Without any more content, a peer closed event should terminate reading
paul@128 133
       from the pipe. */
paul@128 134
paul@128 135
    if (reader->notifications & NOTIFY_PEER_CLOSED)
paul@128 136
    {
paul@128 137
      active--;
paul@128 138
      if (!active)
paul@128 139
        break;
paul@128 140
    }
paul@117 141
  }
paul@117 142
paul@132 143
  client_close(reader1);
paul@132 144
  client_close(reader2);
paul@132 145
paul@117 146
  printf("Data shown.\n");
paul@117 147
}
paul@117 148
paul@65 149
int main(void)
paul@65 150
{
paul@132 151
  /* Invoke the open method to receive the pipe endpoint references. */
paul@65 152
paul@132 153
  file_t *reader1, *reader2, *writer1, *writer2;
paul@132 154
  long err = client_pipe(&reader1, &writer1) || client_pipe(&reader2, &writer2);
paul@65 155
paul@65 156
  if (err)
paul@65 157
  {
paul@123 158
    printf("Could not obtain pipes: %s\n", l4sys_errtostr(err));
paul@65 159
    return 1;
paul@65 160
  }
paul@65 161
paul@117 162
  /* Schedule reader and writer threads. */
paul@117 163
paul@123 164
  std::thread *activities[3];
paul@65 165
paul@132 166
  activities[0] = new std::thread(read_pipes, reader1, reader2);
paul@132 167
  activities[1] = new std::thread(write_pipe, writer1, 1);
paul@132 168
  activities[2] = new std::thread(write_pipe, writer2, 2);
paul@117 169
paul@123 170
  for (int i = 0; i < 3; i++)
paul@117 171
    activities[i]->join();
paul@65 172
}
paul@65 173
paul@65 174
// vim: tabstop=2 expandtab shiftwidth=2