L4Re/departure

Annotated tests/dstest_test_client.cc

391:bc65615a8fed
2022-06-30 Paul Boddie Added missing structure members. mmap-region-flags
paul@18 1
/*
paul@18 2
 * Test dataspace operations.
paul@18 3
 *
paul@330 4
 * Copyright (C) 2020, 2021, 2022 Paul Boddie <paul@boddie.org.uk>
paul@18 5
 *
paul@18 6
 * This program is free software; you can redistribute it and/or
paul@18 7
 * modify it under the terms of the GNU General Public License as
paul@18 8
 * published by the Free Software Foundation; either version 2 of
paul@18 9
 * the License, or (at your option) any later version.
paul@18 10
 *
paul@18 11
 * This program is distributed in the hope that it will be useful,
paul@18 12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
paul@18 13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
paul@18 14
 * GNU General Public License for more details.
paul@18 15
 *
paul@18 16
 * You should have received a copy of the GNU General Public License
paul@18 17
 * along with this program; if not, write to the Free Software
paul@18 18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
paul@18 19
 * Boston, MA  02110-1301, USA
paul@18 20
 */
paul@18 21
paul@18 22
#include <l4/re/env.h>
paul@18 23
#include <l4/sys/err.h>
paul@18 24
paul@85 25
#include <systypes/fcntl.h>
paul@85 26
paul@18 27
#include <stdio.h>
paul@18 28
#include <string.h>
paul@18 29
#include <stdlib.h>
paul@39 30
#include <time.h>
paul@18 31
paul@41 32
#include <system_error>
paul@18 33
#include <thread>
paul@18 34
paul@29 35
#include <ipc/thread.h>
paul@18 36
paul@94 37
#include <fsclient/file.h>
paul@94 38
#include <mem/memory_utils.h>
paul@18 39
paul@18 40
paul@18 41
paul@21 42
/* Test parameters affected by capability limits. */
paul@21 43
paul@18 44
const unsigned long NUMBER_OF_FILES = 10;
paul@18 45
const unsigned int START_LIMIT = 10;
paul@21 46
const unsigned int ACTIVITY_ITERATIONS = 20;
paul@21 47
paul@21 48
/* Test parameters unaffected by any capability limits. */
paul@21 49
paul@18 50
const unsigned int MAP_PAGES = 20;
paul@41 51
const unsigned int REGION_ITERATIONS = 20;
paul@18 52
paul@18 53
paul@18 54
paul@21 55
/* An activity opening and reading from a file. */
paul@18 56
paul@35 57
static long activity(file_t *context, unsigned long fileid, unsigned int start_page)
paul@18 58
{
paul@18 59
  unsigned long step = page(1);
paul@18 60
  unsigned long sample = page(1);
paul@18 61
paul@18 62
  /* Allocate a buffer for sampling from the file. */
paul@18 63
paul@18 64
  char buf[sample + 1];
paul@18 65
paul@18 66
  /* Invoke the open method to receive the file reference. */
paul@18 67
paul@30 68
  file_t file;
paul@18 69
paul@85 70
  long err = file_context_open(&file, O_RDONLY, context);
paul@18 71
paul@18 72
  if (err)
paul@18 73
  {
paul@18 74
    printf("Could not obtain file for %ld @ page %d: %s\n", fileid, start_page, l4sys_errtostr(err));
paul@18 75
    return err;
paul@18 76
  }
paul@18 77
paul@34 78
  /* A region of the file is mapped. */
paul@18 79
paul@339 80
  err = file_mmap(&file, page(start_page), page(MAP_PAGES), 0, 0, file_region_flags(file.flags));
paul@18 81
paul@18 82
  if (err)
paul@18 83
  {
paul@18 84
    printf("Could not map file region for %ld @ page %d: %s\n", fileid, start_page, l4sys_errtostr(err));
paul@30 85
    file_close(&file);
paul@18 86
    return err;
paul@18 87
  }
paul@18 88
paul@21 89
  /* Read the region a number of times. */
paul@18 90
paul@21 91
  for (unsigned int read_counter = 0; read_counter < REGION_ITERATIONS; read_counter++)
paul@21 92
  {
paul@45 93
    for (unsigned long offset = 0; offset < file_populated_span(&file); offset += step)
paul@21 94
    {
paul@45 95
      unsigned long remaining = file_populated_span(&file) - offset;
paul@21 96
      unsigned long sample_remaining = remaining < sample ? remaining : sample;
paul@18 97
paul@30 98
      strncpy(buf, (file.memory + offset), sample_remaining);
paul@21 99
      buf[sample_remaining] = '\0';
paul@21 100
paul@21 101
      /* Test the data obtained. */
paul@18 102
paul@30 103
      unsigned long filepos = file.start_pos + offset;
paul@21 104
      unsigned long _fileid = 0, _filepos = 0;
paul@21 105
      char *sep = strchr(buf, ':');
paul@18 106
paul@21 107
      if (sep != NULL)
paul@21 108
      {
paul@21 109
        *sep = '\0'; sep++;
paul@21 110
        _fileid = atol(buf); _filepos = atol(sep);
paul@21 111
      }
paul@21 112
paul@21 113
      if ((fileid != _fileid) || (filepos != _filepos))
paul@21 114
        printf("! %ld:%ld is not %ld:%ld\n", _fileid, _filepos, fileid, filepos);
paul@18 115
    }
paul@18 116
  }
paul@18 117
paul@30 118
  file_close(&file);
paul@18 119
paul@18 120
  return L4_EOK;
paul@18 121
}
paul@18 122
paul@18 123
paul@18 124
paul@35 125
static long activity_iterate(file_t *context, unsigned long fileid, unsigned int start_page)
paul@18 126
{
paul@18 127
  long err;
paul@18 128
paul@18 129
  /* Open the file, read pages, close the file, over and over. */
paul@18 130
paul@18 131
  for (unsigned int iteration = 0; iteration < ACTIVITY_ITERATIONS; iteration++)
paul@18 132
  {
paul@35 133
    err = activity(context, fileid, start_page);
paul@18 134
    if (err)
paul@18 135
      break;
paul@18 136
  }
paul@18 137
paul@18 138
  return err;
paul@18 139
}
paul@18 140
paul@18 141
paul@18 142
paul@30 143
static long context_for_file(unsigned long fileid, file_t *file, l4_cap_idx_t server)
paul@18 144
{
paul@33 145
  long err = file_context(file, server);
paul@18 146
paul@18 147
  if (err)
paul@18 148
  {
paul@18 149
    printf("Could not obtain context: %s\n", l4sys_errtostr(err));
paul@30 150
    file_close(file);
paul@18 151
    return err;
paul@18 152
  }
paul@18 153
paul@18 154
  /* Write the filename. */
paul@18 155
paul@30 156
  sprintf(file->memory, "%ld", fileid);
paul@18 157
paul@18 158
  return L4_EOK;
paul@18 159
}
paul@18 160
paul@18 161
paul@18 162
paul@18 163
int main(void)
paul@18 164
{
paul@44 165
  long err;
paul@44 166
paul@18 167
  /* Introduce concurrency control. */
paul@18 168
paul@44 169
  err = ipc_thread_init();
paul@44 170
paul@44 171
  if (err)
paul@44 172
  {
paul@44 173
    printf("Initialisation error: %s\n", l4sys_errtostr(err));
paul@44 174
    return 1;
paul@44 175
  }
paul@18 176
paul@30 177
  /* Retain activity and context details. */
paul@30 178
paul@28 179
  std::thread *activities[NUMBER_OF_FILES * START_LIMIT];
paul@30 180
  file_t contexts[NUMBER_OF_FILES];
paul@30 181
paul@30 182
  /* Obtain access to the filesystem. */
paul@30 183
paul@30 184
  l4_cap_idx_t server = l4re_env_get_cap("server");
paul@28 185
paul@28 186
  /* Obtain opener contexts for the files. */
paul@18 187
paul@18 188
  unsigned long fileid;
paul@28 189
paul@28 190
  for (fileid = 0; fileid < NUMBER_OF_FILES; fileid++)
paul@28 191
  {
paul@44 192
    err = context_for_file(fileid, &contexts[fileid], server);
paul@28 193
paul@28 194
    if (err)
paul@28 195
    {
paul@28 196
      printf("Context allocation failed.\n");
paul@28 197
      return 1;
paul@28 198
    }
paul@28 199
  }
paul@28 200
paul@28 201
  /* Start threads accessing all the files. */
paul@28 202
paul@41 203
  printf("Starting threads...\n");
paul@41 204
paul@39 205
  time_t t = time(NULL);
paul@18 206
  int current = 0;
paul@41 207
  unsigned long errors = 0;
paul@18 208
paul@18 209
  for (fileid = 0; fileid < NUMBER_OF_FILES; fileid++)
paul@41 210
  {
paul@28 211
    for (unsigned int start_page = 0; start_page < START_LIMIT; start_page++)
paul@41 212
    {
paul@41 213
      try
paul@41 214
      {
paul@41 215
        activities[current++] = new std::thread(activity_iterate, &contexts[fileid], fileid, start_page);
paul@41 216
      }
paul@41 217
      catch (const std::system_error &exc)
paul@41 218
      {
paul@41 219
        errors++;
paul@41 220
      }
paul@41 221
    }
paul@41 222
  }
paul@18 223
paul@18 224
  /* Wait for the threads. */
paul@18 225
paul@18 226
  int limit = current;
paul@18 227
paul@18 228
  printf("Waiting for %d threads...\n", limit);
paul@18 229
paul@18 230
  for (current = 0; current < limit; current++)
paul@28 231
    activities[current]->join();
paul@28 232
paul@28 233
  /* Discard the contexts. */
paul@28 234
paul@28 235
  for (fileid = 0; fileid < NUMBER_OF_FILES; fileid++)
paul@30 236
    file_close(&contexts[fileid]);
paul@18 237
paul@39 238
  t = time(NULL) - t;
paul@41 239
  printf("Activities completed in %ld seconds (with %ld threads not started).\n", t, errors);
paul@18 240
paul@18 241
  return 0;
paul@18 242
}
paul@31 243
paul@31 244
// vim: tabstop=2 expandtab shiftwidth=2