1 /* 2 * Test pipe operations. 3 * 4 * Copyright (C) 2020, 2021 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #include <l4/re/env.h> 23 #include <l4/sys/err.h> 24 25 #include <thread> 26 27 #include <stdio.h> 28 #include <string.h> 29 #include <stdlib.h> 30 31 #include <fsclient/client.h> 32 #include <fsclient/file.h> 33 #include <mem/memory_utils.h> 34 35 36 37 /* Minimum pipe region size in pages. */ 38 39 const unsigned int PIPE_PAGES = 2; 40 41 /* Use the writer to fill the pipe with data. */ 42 43 static void write_pipe(file_t *writer) 44 { 45 offset_t size = 600; 46 char buffer[size]; 47 48 for (int loop = 0; loop < 3; loop++) 49 { 50 for (int region = 0; region < 26; region++) 51 { 52 memset(buffer, (int) 'a' + region, size); 53 54 offset_t nwritten = client_write(writer, buffer, size); 55 56 printf("Written %ld/%ld in #%d of %d/%d to pipe...\n", nwritten, size, region, loop, 2); 57 } 58 } 59 60 /* Flush to make the final output available. */ 61 62 client_flush(writer); 63 } 64 65 /* Use the reader to obtain data from the pipe. */ 66 67 static void read_pipe(file_t *reader) 68 { 69 offset_t size = 600; 70 char buffer[size]; 71 offset_t nread; 72 73 do 74 { 75 nread = client_read(reader, buffer, size); 76 77 printf("Read %ld/%ld from pipe...\n", nread, size); 78 79 for (offset_t i = 0; i < nread; i += 60) 80 { 81 fwrite(buffer + i, sizeof(char), nread - i > 60 ? 60 : nread - i, stdout); 82 fputs("\n", stdout); 83 } 84 } 85 while (nread); 86 87 printf("Data shown.\n"); 88 } 89 90 int main(void) 91 { 92 /* Obtain access to the filesystem. */ 93 94 l4_cap_idx_t server = l4re_env_get_cap("server"); 95 96 /* Invoke the open method to receive the file reference. */ 97 98 file_t reader, writer; 99 long err = pipe_open(page(PIPE_PAGES), &reader, &writer, server); 100 101 if (err) 102 { 103 printf("Could not obtain pipe: %s\n", l4sys_errtostr(err)); 104 return 1; 105 } 106 107 /* Make the reader and writer blocking to permit synchronisation. */ 108 109 if ((err = client_set_blocking(&reader, true)) || (err = client_set_blocking(&writer, true))) 110 { 111 printf("Could not set as blocking: %s\n", l4sys_errtostr(err)); 112 return 1; 113 } 114 115 /* Schedule reader and writer threads. */ 116 117 std::thread *activities[2]; 118 119 activities[0] = new std::thread(read_pipe, &reader); 120 activities[1] = new std::thread(write_pipe, &writer); 121 122 for (int i = 0; i < 2; i++) 123 activities[i]->join(); 124 } 125 126 // vim: tabstop=2 expandtab shiftwidth=2