ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libeio/eio.c
(Generate patch)

Comparing libeio/eio.c (file contents):
Revision 1.93 by root, Mon Jul 18 01:27:03 2011 UTC vs.
Revision 1.98 by root, Sun Jul 24 05:53:34 2011 UTC

71#endif 71#endif
72#ifndef ELOOP 72#ifndef ELOOP
73# define ELOOP EDOM 73# define ELOOP EDOM
74#endif 74#endif
75 75
76#if !defined(ENOTSOCK) && defined(WSAENOTSOCK)
77# define ENOTSOCK WSAENOTSOCK
78#endif
79
76static void eio_destroy (eio_req *req); 80static void eio_destroy (eio_req *req);
77 81
78#ifndef EIO_FINISH 82#ifndef EIO_FINISH
79# define EIO_FINISH(req) ((req)->finish) && !EIO_CANCELLED (req) ? (req)->finish (req) : 0 83# define EIO_FINISH(req) ((req)->finish) && !EIO_CANCELLED (req) ? (req)->finish (req) : 0
80#endif 84#endif
103 #undef PAGESIZE 107 #undef PAGESIZE
104 #define PAGESIZE 4096 /* GetSystemInfo? */ 108 #define PAGESIZE 4096 /* GetSystemInfo? */
105 109
106 #ifdef EIO_STRUCT_STATI64 110 #ifdef EIO_STRUCT_STATI64
107 #define stat(path,buf) _stati64 (path,buf) 111 #define stat(path,buf) _stati64 (path,buf)
108 #define fstat(fd,buf) _fstati64 (path,buf) 112 #define fstat(fd,buf) _fstati64 (fd,buf)
109 #endif 113 #endif
110 #define lstat(path,buf) stat (path,buf) 114 #define lstat(path,buf) stat (path,buf)
111 #define fsync(fd) (FlushFileBuffers ((HANDLE)EIO_FD_TO_WIN32_HANDLE (fd)) ? 0 : EIO_ERRNO (EBADF, -1)) 115 #define fsync(fd) (FlushFileBuffers ((HANDLE)EIO_FD_TO_WIN32_HANDLE (fd)) ? 0 : EIO_ERRNO (EBADF, -1))
112 #define mkdir(path,mode) _mkdir (path) 116 #define mkdir(path,mode) _mkdir (path)
113 #define link(old,neu) (CreateHardLink (neu, old, 0) ? 0 : EIO_ERRNO (ENOENT, -1)) 117 #define link(old,neu) (CreateHardLink (neu, old, 0) ? 0 : EIO_ERRNO (ENOENT, -1))
160 164
161 #include <sys/time.h> 165 #include <sys/time.h>
162 #include <sys/select.h> 166 #include <sys/select.h>
163 #include <sys/statvfs.h> 167 #include <sys/statvfs.h>
164 #include <unistd.h> 168 #include <unistd.h>
165 #include <utime.h>
166 #include <signal.h> 169 #include <signal.h>
167 #include <dirent.h> 170 #include <dirent.h>
168 171
169 #if _POSIX_MEMLOCK || _POSIX_MEMLOCK_RANGE || _POSIX_MAPPED_FILES 172 #if _POSIX_MEMLOCK || _POSIX_MEMLOCK_RANGE || _POSIX_MAPPED_FILES
170 #include <sys/mman.h> 173 #include <sys/mman.h>
192 195
193 #ifndef EIO_STRUCT_DIRENT 196 #ifndef EIO_STRUCT_DIRENT
194 #define EIO_STRUCT_DIRENT struct dirent 197 #define EIO_STRUCT_DIRENT struct dirent
195 #endif 198 #endif
196 199
200#endif
201
202#if HAVE_UTIMES
203# include <utime.h>
204#endif
205
206#if HAVE_SYS_SYSCALL_H
207# include <sys/syscall.h>
208#endif
209
210#if HAVE_SYS_PRCTL_H
211# include <sys/prctl.h>
197#endif 212#endif
198 213
199#if HAVE_SENDFILE 214#if HAVE_SENDFILE
200# if __linux 215# if __linux
201# include <sys/sendfile.h> 216# include <sys/sendfile.h>
233 248
234/* buffer size for various temporary buffers */ 249/* buffer size for various temporary buffers */
235#define EIO_BUFSIZE 65536 250#define EIO_BUFSIZE 65536
236 251
237#define dBUF \ 252#define dBUF \
238 char *eio_buf; \
239 ETP_WORKER_LOCK (self); \
240 self->dbuf = eio_buf = malloc (EIO_BUFSIZE); \ 253 char *eio_buf = malloc (EIO_BUFSIZE); \
241 ETP_WORKER_UNLOCK (self); \
242 errno = ENOMEM; \ 254 errno = ENOMEM; \
243 if (!eio_buf) \ 255 if (!eio_buf) \
244 return -1; 256 return -1
257
258#define FUBd \
259 free (eio_buf)
245 260
246#define EIO_TICKS ((1000000 + 1023) >> 10) 261#define EIO_TICKS ((1000000 + 1023) >> 10)
247 262
248#define ETP_PRI_MIN EIO_PRI_MIN 263#define ETP_PRI_MIN EIO_PRI_MIN
249#define ETP_PRI_MAX EIO_PRI_MAX 264#define ETP_PRI_MAX EIO_PRI_MAX
254#define ETP_DESTROY(req) eio_destroy (req) 269#define ETP_DESTROY(req) eio_destroy (req)
255static int eio_finish (eio_req *req); 270static int eio_finish (eio_req *req);
256#define ETP_FINISH(req) eio_finish (req) 271#define ETP_FINISH(req) eio_finish (req)
257static void eio_execute (struct etp_worker *self, eio_req *req); 272static void eio_execute (struct etp_worker *self, eio_req *req);
258#define ETP_EXECUTE(wrk,req) eio_execute (wrk,req) 273#define ETP_EXECUTE(wrk,req) eio_execute (wrk,req)
259
260#define ETP_WORKER_CLEAR(req) \
261 if (wrk->dbuf) \
262 { \
263 free (wrk->dbuf); \
264 wrk->dbuf = 0; \
265 }
266
267#define ETP_WORKER_COMMON \
268 void *dbuf;
269 274
270/*****************************************************************************/ 275/*****************************************************************************/
271 276
272#define ETP_NUM_PRI (ETP_PRI_MAX - ETP_PRI_MIN + 1) 277#define ETP_NUM_PRI (ETP_PRI_MAX - ETP_PRI_MIN + 1)
273 278
315 xthread_t tid; 320 xthread_t tid;
316 321
317 /* locked by reslock, reqlock or wrklock */ 322 /* locked by reslock, reqlock or wrklock */
318 ETP_REQ *req; /* currently processed request */ 323 ETP_REQ *req; /* currently processed request */
319 324
325#ifdef ETP_WORKER_COMMON
320 ETP_WORKER_COMMON 326 ETP_WORKER_COMMON
327#endif
321} etp_worker; 328} etp_worker;
322 329
323static etp_worker wrk_first; /* NOT etp */ 330static etp_worker wrk_first; /* NOT etp */
324 331
325#define ETP_WORKER_LOCK(wrk) X_LOCK (wrklock) 332#define ETP_WORKER_LOCK(wrk) X_LOCK (wrklock)
328/* worker threads management */ 335/* worker threads management */
329 336
330static void ecb_cold 337static void ecb_cold
331etp_worker_clear (etp_worker *wrk) 338etp_worker_clear (etp_worker *wrk)
332{ 339{
333 ETP_WORKER_CLEAR (wrk);
334} 340}
335 341
336static void ecb_cold 342static void ecb_cold
337etp_worker_free (etp_worker *wrk) 343etp_worker_free (etp_worker *wrk)
338{ 344{
939#if !HAVE_FDATASYNC 945#if !HAVE_FDATASYNC
940# undef fdatasync 946# undef fdatasync
941# define fdatasync(fd) fsync (fd) 947# define fdatasync(fd) fsync (fd)
942#endif 948#endif
943 949
950static int
951eio__syncfs (int fd)
952{
953 int res;
954
955#if HAVE_SYS_SYNCFS
956 res = (int)syscall (__NR_syncfs, (int)(fd));
957#else
958 res = -1;
959 errno = ENOSYS;
960#endif
961
962 if (res < 0 && errno == ENOSYS && fd >= 0)
963 sync ();
964
965 return res;
966}
967
944/* sync_file_range always needs emulation */ 968/* sync_file_range always needs emulation */
945static int 969static int
946eio__sync_file_range (int fd, off_t offset, size_t nbytes, unsigned int flags) 970eio__sync_file_range (int fd, off_t offset, size_t nbytes, unsigned int flags)
947{ 971{
948#if HAVE_SYNC_FILE_RANGE 972#if HAVE_SYNC_FILE_RANGE
997 pread (fd, eio_buf, len, offset); 1021 pread (fd, eio_buf, len, offset);
998 offset += len; 1022 offset += len;
999 todo -= len; 1023 todo -= len;
1000 } 1024 }
1001 1025
1026 FUBd;
1027
1002 errno = 0; 1028 errno = 0;
1003 return count; 1029 return count;
1004} 1030}
1005 1031
1006#endif 1032#endif
1007 1033
1008/* sendfile always needs emulation */ 1034/* sendfile always needs emulation */
1009static eio_ssize_t 1035static eio_ssize_t
1010eio__sendfile (int ofd, int ifd, off_t offset, size_t count, etp_worker *self) 1036eio__sendfile (int ofd, int ifd, off_t offset, size_t count)
1011{ 1037{
1012 eio_ssize_t written = 0; 1038 eio_ssize_t written = 0;
1013 eio_ssize_t res; 1039 eio_ssize_t res;
1014 1040
1015 if (!count) 1041 if (!count)
1151 1177
1152 offset += cnt; 1178 offset += cnt;
1153 res += cnt; 1179 res += cnt;
1154 count -= cnt; 1180 count -= cnt;
1155 } 1181 }
1182
1183 FUBd;
1156 } 1184 }
1157 1185
1158 return res; 1186 return res;
1159} 1187}
1160 1188
1889{ 1917{
1890 ETP_REQ *req; 1918 ETP_REQ *req;
1891 struct timespec ts; 1919 struct timespec ts;
1892 etp_worker *self = (etp_worker *)thr_arg; 1920 etp_worker *self = (etp_worker *)thr_arg;
1893 1921
1922#if HAVE_PRCTL_SET_NAME
1923 prctl (PR_SET_NAME, (unsigned long)"eio_thread", 0, 0, 0);
1924#endif
1925
1894 /* try to distribute timeouts somewhat evenly */ 1926 /* try to distribute timeouts somewhat evenly */
1895 ts.tv_nsec = ((unsigned long)self & 1023UL) * (1000000000UL / 1024UL); 1927 ts.tv_nsec = ((unsigned long)self & 1023UL) * (1000000000UL / 1024UL);
1896 1928
1897 for (;;) 1929 for (;;)
1898 { 1930 {
2025 case EIO_WRITE: req->result = req->offs >= 0 2057 case EIO_WRITE: req->result = req->offs >= 0
2026 ? pwrite (req->int1, req->ptr2, req->size, req->offs) 2058 ? pwrite (req->int1, req->ptr2, req->size, req->offs)
2027 : write (req->int1, req->ptr2, req->size); break; 2059 : write (req->int1, req->ptr2, req->size); break;
2028 2060
2029 case EIO_READAHEAD: req->result = readahead (req->int1, req->offs, req->size); break; 2061 case EIO_READAHEAD: req->result = readahead (req->int1, req->offs, req->size); break;
2030 case EIO_SENDFILE: req->result = eio__sendfile (req->int1, req->int2, req->offs, req->size, self); break; 2062 case EIO_SENDFILE: req->result = eio__sendfile (req->int1, req->int2, req->offs, req->size); break;
2031 2063
2032 case EIO_STAT: ALLOC (sizeof (EIO_STRUCT_STAT)); 2064 case EIO_STAT: ALLOC (sizeof (EIO_STRUCT_STAT));
2033 req->result = stat (req->ptr1, (EIO_STRUCT_STAT *)req->ptr2); break; 2065 req->result = stat (req->ptr1, (EIO_STRUCT_STAT *)req->ptr2); break;
2034 case EIO_LSTAT: ALLOC (sizeof (EIO_STRUCT_STAT)); 2066 case EIO_LSTAT: ALLOC (sizeof (EIO_STRUCT_STAT));
2035 req->result = lstat (req->ptr1, (EIO_STRUCT_STAT *)req->ptr2); break; 2067 req->result = lstat (req->ptr1, (EIO_STRUCT_STAT *)req->ptr2); break;
2065 req->result = readlink (req->ptr1, req->ptr2, PATH_MAX); break; 2097 req->result = readlink (req->ptr1, req->ptr2, PATH_MAX); break;
2066 2098
2067 case EIO_SYNC: req->result = 0; sync (); break; 2099 case EIO_SYNC: req->result = 0; sync (); break;
2068 case EIO_FSYNC: req->result = fsync (req->int1); break; 2100 case EIO_FSYNC: req->result = fsync (req->int1); break;
2069 case EIO_FDATASYNC: req->result = fdatasync (req->int1); break; 2101 case EIO_FDATASYNC: req->result = fdatasync (req->int1); break;
2102 case EIO_SYNCFS: req->result = eio__syncfs (req->int1); break;
2103 case EIO_SYNC_FILE_RANGE: req->result = eio__sync_file_range (req->int1, req->offs, req->size, req->int2); break;
2070 case EIO_MSYNC: req->result = eio__msync (req->ptr2, req->size, req->int1); break; 2104 case EIO_MSYNC: req->result = eio__msync (req->ptr2, req->size, req->int1); break;
2071 case EIO_MTOUCH: req->result = eio__mtouch (req); break; 2105 case EIO_MTOUCH: req->result = eio__mtouch (req); break;
2072 case EIO_MLOCK: req->result = eio__mlock (req->ptr2, req->size); break; 2106 case EIO_MLOCK: req->result = eio__mlock (req->ptr2, req->size); break;
2073 case EIO_MLOCKALL: req->result = eio__mlockall (req->int1); break; 2107 case EIO_MLOCKALL: req->result = eio__mlockall (req->int1); break;
2074 case EIO_SYNC_FILE_RANGE: req->result = eio__sync_file_range (req->int1, req->offs, req->size, req->int2); break;
2075 case EIO_FALLOCATE: req->result = eio__fallocate (req->int1, req->int2, req->offs, req->size); break; 2108 case EIO_FALLOCATE: req->result = eio__fallocate (req->int1, req->int2, req->offs, req->size); break;
2076 2109
2077 case EIO_READDIR: eio__scandir (req, self); break; 2110 case EIO_READDIR: eio__scandir (req, self); break;
2078 2111
2079 case EIO_BUSY: 2112 case EIO_BUSY:
2160eio_req *eio_msync (void *addr, size_t length, int flags, int pri, eio_cb cb, void *data) 2193eio_req *eio_msync (void *addr, size_t length, int flags, int pri, eio_cb cb, void *data)
2161{ 2194{
2162 REQ (EIO_MSYNC); req->ptr2 = addr; req->size = length; req->int1 = flags; SEND; 2195 REQ (EIO_MSYNC); req->ptr2 = addr; req->size = length; req->int1 = flags; SEND;
2163} 2196}
2164 2197
2198eio_req *eio_fdatasync (int fd, int pri, eio_cb cb, void *data)
2199{
2200 REQ (EIO_FDATASYNC); req->int1 = fd; SEND;
2201}
2202
2203eio_req *eio_syncfs (int fd, int pri, eio_cb cb, void *data)
2204{
2205 REQ (EIO_SYNCFS); req->int1 = fd; SEND;
2206}
2207
2208eio_req *eio_sync_file_range (int fd, off_t offset, size_t nbytes, unsigned int flags, int pri, eio_cb cb, void *data)
2209{
2210 REQ (EIO_SYNC_FILE_RANGE); req->int1 = fd; req->offs = offset; req->size = nbytes; req->int2 = flags; SEND;
2211}
2212
2165eio_req *eio_mtouch (void *addr, size_t length, int flags, int pri, eio_cb cb, void *data) 2213eio_req *eio_mtouch (void *addr, size_t length, int flags, int pri, eio_cb cb, void *data)
2166{ 2214{
2167 REQ (EIO_MTOUCH); req->ptr2 = addr; req->size = length; req->int1 = flags; SEND; 2215 REQ (EIO_MTOUCH); req->ptr2 = addr; req->size = length; req->int1 = flags; SEND;
2168} 2216}
2169 2217
2175eio_req *eio_mlockall (int flags, int pri, eio_cb cb, void *data) 2223eio_req *eio_mlockall (int flags, int pri, eio_cb cb, void *data)
2176{ 2224{
2177 REQ (EIO_MLOCKALL); req->int1 = flags; SEND; 2225 REQ (EIO_MLOCKALL); req->int1 = flags; SEND;
2178} 2226}
2179 2227
2180eio_req *eio_sync_file_range (int fd, off_t offset, size_t nbytes, unsigned int flags, int pri, eio_cb cb, void *data)
2181{
2182 REQ (EIO_SYNC_FILE_RANGE); req->int1 = fd; req->offs = offset; req->size = nbytes; req->int2 = flags; SEND;
2183}
2184
2185eio_req *eio_fallocate (int fd, int mode, off_t offset, size_t len, int pri, eio_cb cb, void *data) 2228eio_req *eio_fallocate (int fd, int mode, off_t offset, size_t len, int pri, eio_cb cb, void *data)
2186{ 2229{
2187 REQ (EIO_FALLOCATE); req->int1 = fd; req->int2 = mode; req->offs = offset; req->size = len; SEND; 2230 REQ (EIO_FALLOCATE); req->int1 = fd; req->int2 = mode; req->offs = offset; req->size = len; SEND;
2188}
2189
2190eio_req *eio_fdatasync (int fd, int pri, eio_cb cb, void *data)
2191{
2192 REQ (EIO_FDATASYNC); req->int1 = fd; SEND;
2193} 2231}
2194 2232
2195eio_req *eio_close (int fd, int pri, eio_cb cb, void *data) 2233eio_req *eio_close (int fd, int pri, eio_cb cb, void *data)
2196{ 2234{
2197 REQ (EIO_CLOSE); req->int1 = fd; SEND; 2235 REQ (EIO_CLOSE); req->int1 = fd; SEND;
2425/* misc garbage */ 2463/* misc garbage */
2426 2464
2427eio_ssize_t 2465eio_ssize_t
2428eio_sendfile_sync (int ofd, int ifd, off_t offset, size_t count) 2466eio_sendfile_sync (int ofd, int ifd, off_t offset, size_t count)
2429{ 2467{
2430 etp_worker wrk;
2431 eio_ssize_t ret;
2432
2433 wrk.dbuf = 0;
2434
2435 ret = eio__sendfile (ofd, ifd, offset, count, &wrk); 2468 return eio__sendfile (ofd, ifd, offset, count);
2436
2437 if (wrk.dbuf)
2438 free (wrk.dbuf);
2439
2440 return ret;
2441} 2469}
2442 2470

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines