additional tests, fixes, move some functions to ../lib
[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 #define BUFSZ N_SAMPLES*sizeof(sampl_t)
26
27 #define MAPLEN 20480
28
29 jmp_buf jump_env;
30
31 void segv_handler(int num,siginfo_t *si,void *x)
32 {
33         longjmp(jump_env,1);
34 }
35
36 int test_segfault(void *memptr)
37 {
38         volatile char tmp;
39         int ret;
40
41         ret=setjmp(jump_env);
42         if(!ret) tmp = *((char *)(memptr));
43         return ret;
44 }
45
46 void setup_segfaulter(void)
47 {
48         struct sigaction act;
49
50         memset(&act,0,sizeof(act));
51         act.sa_sigaction=&segv_handler;
52         act.sa_flags = SA_SIGINFO;
53         sigaction(SIGSEGV,&act,NULL);
54 }
55
56 int test_mmap(void)
57 {
58         comedi_cmd cmd;
59         char *buf;
60         unsigned int chanlist[1];
61         int go;
62         int total=0;
63         int ret;
64         void *b, *adr;
65         sampl_t *map;
66
67         if(!(comedi_get_subdevice_flags(device,subdevice)&SDF_CMD)){
68                 printf("not applicable\n");
69                 return 0;
70         }
71
72         if(comedi_get_cmd_generic_timed(device,subdevice,&cmd)<0){
73                 printf("E: comedi_get_cmd_generic_timed failed\n");
74                 return 0;
75         }
76
77         setup_segfaulter();
78
79         buf=malloc(BUFSZ);
80
81         map=mmap(NULL,MAPLEN,PROT_READ,MAP_SHARED,comedi_fileno(device),0);
82         if(!map){
83                 printf("E: mmap() failed\n");
84                 return 0;
85         }
86
87         /* test readability */
88         for(adr=map;adr<(void *)map+MAPLEN;adr+=PAGE_SIZE){
89                 ret=test_segfault(adr);
90                 if(ret){
91                         printf("E: %p failed\n",adr);
92                 }else{
93                         printf("%p ok\n",adr);
94                 }
95         }
96
97         cmd.chanlist = chanlist;
98         cmd.scan_end_arg = 1;
99         cmd.stop_arg = N_SAMPLES;
100         cmd.chanlist_len = 1;
101         chanlist[0] = CR_PACK(0,0,0);
102
103         comedi_command(device,&cmd);
104
105         go=1;
106         b=buf;
107         while(go){
108                 ret = read(comedi_fileno(device),b,BUFSZ);
109                 if(ret<0){
110                         if(errno==EAGAIN){
111                                 usleep(10000);
112                         }else{
113                                 go = 0;
114                                 perror("read");
115                         }
116                 }else if(ret==0){
117                         go = 0;
118                 }else{
119                         total += ret;
120                         b += ret;
121                         printf("read %d %d\n",ret,total);
122                 }
123         }
124         if(memcmp(buf,map,total)){
125                 printf("E: mmap compare failed\n");
126         }else{
127                 printf("compare ok\n");
128         }
129         munmap(map,MAPLEN);
130
131         /* test if area is really unmapped */
132         for(adr=map;adr<(void *)map+MAPLEN;adr+=PAGE_SIZE){
133                 ret=test_segfault(adr);
134                 if(ret){
135                         printf("%p segfaulted (ok)\n",adr);
136                 }else{
137                         printf("E: %p still mapped\n",adr);
138                 }
139         }
140
141         free(buf);
142
143         return 0;
144 }
145