[660] | 1 | /////////////////////////////////////////////////////////////////////////////////////// |
---|
| 2 | // file : kleenex.c |
---|
| 3 | // date : november 2019 |
---|
| 4 | // author : Alain Greiner |
---|
| 5 | /////////////////////////////////////////////////////////////////////////////////////// |
---|
| 6 | // This file describes the single thread "kleenex" application. |
---|
| 7 | // That makes a copy of a file from one input file to another output file. |
---|
| 8 | // - the first implementation uses the read / write syscalls. |
---|
| 9 | // - the second implementation uses the mmap / munmap syscalls. |
---|
| 10 | /////////////////////////////////////////////////////////////////////////////////////// |
---|
| 11 | |
---|
| 12 | #include <pthread.h> |
---|
| 13 | #include <sys/mman.h> |
---|
| 14 | #include <stdio.h> |
---|
| 15 | #include <stdlib.h> |
---|
| 16 | #include <fcntl.h> |
---|
| 17 | #include <sys/stat.h> |
---|
| 18 | #include <unistd.h> |
---|
| 19 | #include <almosmkh.h> |
---|
| 20 | |
---|
[676] | 21 | #define IN_FILENAME "misc/philips_1024.raw" |
---|
| 22 | #define OUT_FILENAME "misc/philips_1024.new" |
---|
[660] | 23 | #define FBF_TYPE 420 |
---|
| 24 | #define NPIXELS 1024 |
---|
| 25 | #define NLINES 1024 |
---|
| 26 | |
---|
| 27 | //////////////// |
---|
| 28 | int main( void ) |
---|
| 29 | { |
---|
| 30 | int fd_in; |
---|
| 31 | int fd_out; |
---|
| 32 | |
---|
[676] | 33 | int fbf_width; |
---|
| 34 | int fbf_height; |
---|
| 35 | int fbf_type; |
---|
[660] | 36 | |
---|
| 37 | int line; |
---|
| 38 | int pixel; |
---|
| 39 | |
---|
| 40 | int error; |
---|
| 41 | |
---|
| 42 | unsigned long long start_cycle; |
---|
| 43 | |
---|
[676] | 44 | unsigned char buf_in[NPIXELS * NLINES]; |
---|
[660] | 45 | unsigned char buf_out[NPIXELS * NLINES]; |
---|
| 46 | |
---|
| 47 | struct stat st; |
---|
| 48 | |
---|
[676] | 49 | int size_in = NPIXELS * NLINES; |
---|
[660] | 50 | int size_out = NPIXELS * NLINES; |
---|
| 51 | |
---|
| 52 | // get start cycle |
---|
| 53 | get_cycle( &start_cycle ); |
---|
| 54 | |
---|
| 55 | printf("\n[kleenex] starts at cycle %d\n", (unsigned int)start_cycle ); |
---|
| 56 | |
---|
| 57 | // check frame buffer size |
---|
| 58 | fbf_get_config( &fbf_width , &fbf_height , &fbf_type ); |
---|
| 59 | |
---|
| 60 | if( (NPIXELS != fbf_width) || (NLINES != fbf_height) ) |
---|
| 61 | { |
---|
| 62 | printf("\n[kleenex error] FBF size [%d,%d] does not fit image size[%d,%d]\n", |
---|
| 63 | fbf_width, fbf_height, NPIXELS, NLINES ); |
---|
| 64 | exit( 0 ); |
---|
| 65 | } |
---|
| 66 | |
---|
| 67 | if( fbf_type != FBF_TYPE ) |
---|
| 68 | { |
---|
| 69 | printf("\n[kleenex error] FBF type [%d] does not fit image type [%d]\n", |
---|
| 70 | fbf_type, FBF_TYPE); |
---|
| 71 | exit( 0 ); |
---|
| 72 | } |
---|
| 73 | |
---|
| 74 | ////////// open input file |
---|
| 75 | fd_in = open( IN_FILENAME , O_RDONLY , 0 ); |
---|
| 76 | |
---|
| 77 | if( fd_in < 0 ) |
---|
| 78 | { |
---|
| 79 | printf("\n[kleenex error] Cannot open file <%s>\n", IN_FILENAME ); |
---|
| 80 | exit( 0 ); |
---|
| 81 | } |
---|
| 82 | |
---|
| 83 | printf("\n[kleenex] open file <%s>\n", IN_FILENAME ); |
---|
| 84 | |
---|
| 85 | ////////// open output file |
---|
| 86 | fd_out = open( OUT_FILENAME , O_CREAT , 0 ); |
---|
| 87 | |
---|
| 88 | if( fd_out < 0 ) |
---|
| 89 | { |
---|
| 90 | printf("\n[kleenex error] Cannot open file <%s>\n", OUT_FILENAME ); |
---|
| 91 | exit( 0 ); |
---|
| 92 | } |
---|
| 93 | |
---|
| 94 | printf("\n[kleenex] open file <%s>\n", OUT_FILENAME ); |
---|
| 95 | |
---|
| 96 | ////////// copy input image file to buf_in |
---|
| 97 | if( read( fd_in , buf_in , size_in ) != size_in ) |
---|
| 98 | { |
---|
| 99 | printf("\n[kleenex error] Cannot read file <%s>\n", IN_FILENAME ); |
---|
| 100 | exit( 0 ); |
---|
| 101 | } |
---|
| 102 | |
---|
| 103 | printf("\n[kleenex] copied file <%s> to buf_in\n", IN_FILENAME ); |
---|
| 104 | |
---|
| 105 | ////////// copy buf_in to buf_out |
---|
| 106 | for( line = 0 ; line < NLINES ; line++ ) |
---|
| 107 | { |
---|
| 108 | for( pixel = 0 ; pixel < NPIXELS ; pixel++ ) |
---|
| 109 | { |
---|
| 110 | unsigned int index = (line*NPIXELS) + pixel; |
---|
[676] | 111 | buf_out[index] = buf_in[index]; |
---|
[660] | 112 | } |
---|
| 113 | } |
---|
| 114 | |
---|
| 115 | printf("\n[kleenex] moved buf_in to buf_out\n" ); |
---|
| 116 | |
---|
| 117 | ////////// display output image |
---|
| 118 | error = fbf_write( buf_out , size_out , 0 ); |
---|
| 119 | |
---|
| 120 | if(error) |
---|
| 121 | { |
---|
| 122 | printf("\n[kleenex error] cannot display buf_out\n"); |
---|
| 123 | exit( 0 ); |
---|
| 124 | } |
---|
| 125 | |
---|
| 126 | ////////// copy buf_out to to output image file |
---|
| 127 | if( write( fd_out , buf_out , size_out ) != size_out ) |
---|
| 128 | { |
---|
| 129 | printf("\n[kleenex error] Cannot write file <%s>\n", OUT_FILENAME ); |
---|
| 130 | exit( 0 ); |
---|
| 131 | } |
---|
| 132 | |
---|
| 133 | printf("\n[kleenex] copied buf_out to file <%s>\n", OUT_FILENAME ); |
---|
| 134 | |
---|
| 135 | ///////// check output file size |
---|
| 136 | if ( stat( OUT_FILENAME , &st ) == -1) |
---|
| 137 | { |
---|
| 138 | printf(" error: cannot stat <%s>\n", OUT_FILENAME ); |
---|
| 139 | } |
---|
| 140 | else |
---|
| 141 | { |
---|
| 142 | printf("\n[kleenex] size = %x for file <%s>\n", st.st_size , OUT_FILENAME ); |
---|
| 143 | } |
---|
| 144 | |
---|
| 145 | ///////// close input file |
---|
| 146 | close( fd_in ); |
---|
| 147 | |
---|
| 148 | printf("\n[kleenex] closed file <%s>\n", IN_FILENAME ); |
---|
| 149 | |
---|
| 150 | //////// close output file |
---|
| 151 | close( fd_out ); |
---|
| 152 | |
---|
| 153 | printf("\n[kleenex] closed file <%s>\n", OUT_FILENAME ); |
---|
| 154 | |
---|
| 155 | exit(0); |
---|
| 156 | |
---|
| 157 | return 0; |
---|
| 158 | } |
---|
| 159 | |
---|
| 160 | |
---|
| 161 | /* Another implementation using using the mmap / munmap syscalls |
---|
| 162 | |
---|
| 163 | int main( void ) |
---|
| 164 | { |
---|
| 165 | int fd_in; |
---|
| 166 | int fd_out; |
---|
| 167 | |
---|
| 168 | unsigned int fbf_width; |
---|
| 169 | unsigned int fbf_height; |
---|
| 170 | unsigned int fbf_type; |
---|
| 171 | |
---|
| 172 | int line; |
---|
| 173 | int pixel; |
---|
| 174 | |
---|
| 175 | int error; |
---|
| 176 | |
---|
| 177 | unsigned long long start_cycle; |
---|
| 178 | |
---|
| 179 | |
---|
| 180 | unsigned short * buf_in; |
---|
| 181 | unsigned char * buf_out; |
---|
| 182 | |
---|
| 183 | struct stat st; |
---|
| 184 | |
---|
| 185 | int size_in = NPIXELS * NLINES; |
---|
| 186 | int size_out = NPIXELS * NLINES; |
---|
| 187 | |
---|
| 188 | // get start cycle |
---|
| 189 | get_cycle( &start_cycle ); |
---|
| 190 | |
---|
| 191 | printf("\n[kleenex] starts at cycle %d\n", (unsigned int)start_cycle ); |
---|
| 192 | |
---|
| 193 | // check frame buffer size |
---|
| 194 | fbf_get_config( &fbf_width , &fbf_height , &fbf_type ); |
---|
| 195 | |
---|
| 196 | if( (NPIXELS != fbf_width) || (NLINES != fbf_height) ) |
---|
| 197 | { |
---|
| 198 | printf("\n[kleenex error] FBF size [%d,%d] does not fit image size[%d,%d]\n", |
---|
| 199 | fbf_width, fbf_height, NPIXELS, NLINES ); |
---|
| 200 | exit( 0 ); |
---|
| 201 | } |
---|
| 202 | |
---|
| 203 | if( fbf_type != FBF_TYPE ) |
---|
| 204 | { |
---|
| 205 | printf("\n[kleenex error] FBF type [%d] does not fit image type [%d]\n", |
---|
| 206 | fbf_type, FBF_TYPE); |
---|
| 207 | exit( 0 ); |
---|
| 208 | } |
---|
| 209 | |
---|
| 210 | // open input file |
---|
| 211 | fd_in = open( IN_FILENAME , O_RDONLY , 0 ); |
---|
| 212 | |
---|
| 213 | if( fd_in < 0 ) |
---|
| 214 | { |
---|
| 215 | printf("\n[kleenex error] Cannot open file <%s>\n", IN_FILENAME ); |
---|
| 216 | exit( 0 ); |
---|
| 217 | } |
---|
| 218 | |
---|
| 219 | printf("\n[kleenex] open file <%s>\n", IN_FILENAME ); |
---|
| 220 | |
---|
| 221 | // open output file |
---|
| 222 | fd_out = open( OUT_FILENAME , O_CREAT , 0 ); |
---|
| 223 | |
---|
| 224 | if( fd_out < 0 ) |
---|
| 225 | { |
---|
| 226 | printf("\n[kleenex error] Cannot open file <%s>\n", OUT_FILENAME ); |
---|
| 227 | exit( 0 ); |
---|
| 228 | } |
---|
| 229 | |
---|
| 230 | printf("\n[kleenex] open file <%s>\n", OUT_FILENAME ); |
---|
| 231 | |
---|
| 232 | // TODO we must write one byte at the end of the output file |
---|
| 233 | // to set the size of this file, and make the mmap() successful |
---|
| 234 | |
---|
| 235 | // check output file size |
---|
| 236 | if ( stat( OUT_FILENAME , &st ) == -1) |
---|
| 237 | { |
---|
| 238 | printf(" error: cannot stat <%s>\n", OUT_FILENAME ); |
---|
| 239 | } |
---|
| 240 | else |
---|
| 241 | { |
---|
| 242 | printf("\n[kleenex] size = %x for file <%s>\n", st.st_size , OUT_FILENAME ); |
---|
| 243 | } |
---|
| 244 | |
---|
| 245 | // map buf_in to input file |
---|
| 246 | buf_in = (unsigned short *)mmap( NULL, |
---|
| 247 | NPIXELS * NLINES * 2, |
---|
| 248 | PROT_READ, |
---|
| 249 | MAP_FILE | MAP_SHARED, |
---|
| 250 | fd_in, |
---|
| 251 | 0 ); // offset |
---|
| 252 | if ( buf_in == NULL ) |
---|
| 253 | { |
---|
| 254 | printf("\n[kleenex error] cannot map buf_in to file %s\n", IN_FILENAME ); |
---|
| 255 | exit( 0 ); |
---|
| 256 | } |
---|
| 257 | |
---|
| 258 | printf("\n[kleenex] map buf_in to file <%s>\n", IN_FILENAME ); |
---|
| 259 | |
---|
| 260 | // map buf_out to output file |
---|
| 261 | buf_out = (unsigned char *)mmap( NULL, |
---|
| 262 | NPIXELS * NLINES, |
---|
| 263 | PROT_WRITE, |
---|
| 264 | MAP_FILE | MAP_SHARED, |
---|
| 265 | fd_out, |
---|
| 266 | 0 ); // offset |
---|
| 267 | if ( buf_out == NULL ) |
---|
| 268 | { |
---|
| 269 | printf("\n[kleenex error] cannot map buf_out to file %s\n", OUT_FILENAME ); |
---|
| 270 | exit( 0 ); |
---|
| 271 | } |
---|
| 272 | |
---|
| 273 | printf("\n[kleenex] map buf_out to file <%s>\n", OUT_FILENAME ); |
---|
| 274 | |
---|
| 275 | // copy buf_in to buf_out |
---|
| 276 | for( line = 0 ; line < NLINES ; line++ ) |
---|
| 277 | { |
---|
| 278 | for( pixel = 0 ; pixel < NPIXELS ; pixel++ ) |
---|
| 279 | { |
---|
| 280 | unsigned int index = (line*NPIXELS) + pixel; |
---|
| 281 | buf_out[index] = buf_in[index]; |
---|
| 282 | } |
---|
| 283 | } |
---|
| 284 | |
---|
| 285 | printf("\n[kleenex] moved buf_in to buf_out\n" ); |
---|
| 286 | |
---|
| 287 | // display output image |
---|
| 288 | error = fbf_write( buf_out , size_out , 0 ); |
---|
| 289 | |
---|
| 290 | if(error) |
---|
| 291 | { |
---|
| 292 | printf("\n[kleenex error] cannot display buf_out\n"); |
---|
| 293 | exit( 0 ); |
---|
| 294 | } |
---|
| 295 | |
---|
| 296 | // unmap buf_in |
---|
| 297 | munmap( buf_in , NPIXELS * NLINES * 2 ); |
---|
| 298 | |
---|
| 299 | // printf("\n[kleenex] unmap buf_in\n" ); |
---|
| 300 | |
---|
| 301 | // close input file |
---|
| 302 | close( fd_in ); |
---|
| 303 | |
---|
| 304 | printf("\n[kleenex] closed file <%s>\n", IN_FILENAME ); |
---|
| 305 | |
---|
| 306 | // unmap buf_out |
---|
| 307 | munmap( buf_out , NPIXELS * NLINES ); |
---|
| 308 | |
---|
| 309 | // printf("\n[kleenex] unmap buf_out\n" ); |
---|
| 310 | |
---|
| 311 | // close output file |
---|
| 312 | close( fd_out ); |
---|
| 313 | |
---|
| 314 | printf("\n[kleenex] closed file <%s>\n", OUT_FILENAME ); |
---|
| 315 | |
---|
| 316 | exit(0); |
---|
| 317 | |
---|
| 318 | return 0; |
---|
| 319 | } |
---|
| 320 | |
---|
| 321 | */ |
---|