comedi_board_info: Moved man page into ../man
[comedilib.git] / testing / mmap.c
1
2 #include <stdio.h>
3 #include <comedilib.h>
4 #include <fcntl.h>
5 #include <unistd.h>
6 #include <sys/ioctl.h>
7 #include <errno.h>
8 #include <getopt.h>
9 #include <ctype.h>
10 #include <math.h>
11 #include <sys/time.h>
12 #include <string.h>
13 #include <sys/mman.h>
14 #include <signal.h>
15 #include <setjmp.h>
16 #include <stdlib.h>
17
18 #include "comedi_test.h"
19
20 /* XXX this should come from elsewhere */
21 #define PAGE_SIZE 4096
22
23 #define N_SAMPLES 10000
24
25 sigjmp_buf jump_env;
26
27 void segv_handler(int num)
28 {
29         siglongjmp(jump_env,1);
30 }
31
32 int test_segfault(void *memptr)
33 {
34         volatile char tmp;
35         int ret;
36         struct sigaction act;
37         struct sigaction oldact;
38
39         memset(&act,0,sizeof(act));
40         act.sa_handler=&segv_handler;
41         ret = sigaction(SIGSEGV,&act,&oldact);
42         if(ret)
43         {
44                 fprintf(stderr, "sigaction failed\n");
45                 return 0;
46         }
47         ret=sigsetjmp(jump_env, 1);
48         if(!ret) tmp = *((char *)(memptr));
49         sigaction(SIGSEGV,&oldact,NULL);
50         return ret;
51 }
52
53 int test_mmap(void)
54 {
55         comedi_cmd cmd;
56         unsigned char *buf;
57         unsigned int chanlist[1];
58         int go;
59         int fails;
60         int total=0;
61         int ret;
62         void *b;
63         unsigned char *adr;
64         unsigned char *map;
65         unsigned int flags;
66         int i;
67         unsigned sample_size;
68         unsigned map_len;
69
70         flags = comedi_get_subdevice_flags(device,subdevice);
71
72         if(!(flags&SDF_CMD) || (comedi_get_read_subdevice(device)!=subdevice)){
73                 printf("not applicable\n");
74                 return 0;
75         }
76         if(flags & SDF_LSAMPL) sample_size = sizeof(lsampl_t);
77         else sample_size = sizeof(sampl_t);
78         map_len = sample_size * N_SAMPLES;
79
80         if(comedi_get_cmd_generic_timed(device, subdevice, &cmd, 1, 1)<0){
81                 printf("E: comedi_get_cmd_generic_timed failed\n");
82                 return 0;
83         }
84
85         buf=malloc(sample_size * N_SAMPLES);
86
87         map = mmap(NULL, map_len,PROT_READ, MAP_SHARED, comedi_fileno(device),0);
88         if(!map){
89                 printf("E: mmap() failed\n");
90                 return 0;
91         }
92
93         /* test readability */
94         for(adr = map; adr < map + map_len; adr += PAGE_SIZE){
95                 ret=test_segfault(adr);
96                 if(ret){
97                         printf("E: %p failed\n",adr);
98                 }else{
99                         printf("%p ok\n",adr);
100                 }
101         }
102
103         if(realtime)cmd.flags |= TRIG_RT;
104
105         cmd.chanlist = chanlist;
106         cmd.scan_end_arg = 1;
107         cmd.stop_arg = N_SAMPLES;
108         cmd.chanlist_len = 1;
109         chanlist[0] = CR_PACK(0,0,0);
110
111         comedi_command(device,&cmd);
112
113         go=1;
114         b=buf;
115         while(go){
116                 ret = read(comedi_fileno(device), b,
117                                 (N_SAMPLES * sample_size) - total);
118                 if(ret<0){
119                         if(errno==EAGAIN){
120                                 usleep(10000);
121                         }else{
122                                 go = 0;
123                                 perror("read");
124                         }
125                 }else if(ret==0){
126                         go = 0;
127                 }else{
128                         total += ret;
129                         b += ret;
130                         if(verbose) printf("read %d %d\n",ret,total);
131                         if(total >= (N_SAMPLES * sample_size)){
132                                 go = 0;
133                         }
134                 }
135         }
136
137         fails = 0;
138         for(i=0;i<total;i++){
139                 if(buf[i]!=map[i]){
140                         if(fails==0)printf("E: mmap compare failed\n");
141                         printf("offset %d (read=%02x mmap=%02x)\n",i,
142                                 buf[i], map[i]);
143                         fails++;
144                         if(fails>10)break;
145                 }
146         }
147         if(fails==0) printf("compare ok\n");
148
149         munmap(map, map_len);
150
151         /* test if area is really unmapped */
152         for(adr = map; adr < map + map_len; adr += PAGE_SIZE){
153                 ret=test_segfault(adr);
154                 if(ret){
155                         printf("%p segfaulted (ok)\n",adr);
156                 }else{
157                         printf("E: %p still mapped\n",adr);
158                 }
159         }
160
161         free(buf);
162
163         return 0;
164 }
165