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

Comparing libeio/eio.c (file contents):
Revision 1.84 by root, Thu Jul 7 22:39:56 2011 UTC vs.
Revision 1.89 by root, Thu Jul 14 22:36:17 2011 UTC

54#include <stdlib.h> 54#include <stdlib.h>
55#include <string.h> 55#include <string.h>
56#include <errno.h> 56#include <errno.h>
57#include <sys/types.h> 57#include <sys/types.h>
58#include <sys/stat.h> 58#include <sys/stat.h>
59#include <sys/statvfs.h>
60#include <limits.h> 59#include <limits.h>
61#include <fcntl.h> 60#include <fcntl.h>
62#include <assert.h> 61#include <assert.h>
63 62
64/* intptr_t comes from unistd.h, says POSIX/UNIX/tradition */ 63/* intptr_t comes from unistd.h, says POSIX/UNIX/tradition */
83 82
84#ifndef EIO_FEED 83#ifndef EIO_FEED
85# define EIO_FEED(req) do { if ((req)->feed ) (req)->feed (req); } while (0) 84# define EIO_FEED(req) do { if ((req)->feed ) (req)->feed (req); } while (0)
86#endif 85#endif
87 86
87#ifndef EIO_FD_TO_WIN32_HANDLE
88# define EIO_FD_TO_WIN32_HANDLE(fd) _get_osfhandle (fd)
89#endif
90#ifndef EIO_WIN32_HANDLE_TO_FD
91# define EIO_WIN32_HANDLE_TO_FD(handle) _open_osfhandle (handle, 0)
92#endif
93
94#define EIO_ERRNO(errval,retval) ((errno = errval), retval)
95
96#define EIO_ENOSYS() EIO_ERRNO (ENOSYS, -1)
97
88#ifdef _WIN32 98#ifdef _WIN32
89 99
90 /*doh*/ 100 #define PAGESIZE 4096 /* GetSystemInfo? */
101
102 #ifdef EIO_STRUCT_STATI64
103 #define stat(path,buf) _stati64 (path,buf)
104 #define fstat(fd,buf) _fstati64 (path,buf)
105 #endif
106 #define lstat(path,buf) stat (path,buf)
107 #define fsync(fd) (FlushFileBuffers (EIO_FD_TO_WIN32_HANDLE (fd)) ? 0 : EIO_ERRNO (EBADF, -1))
108 #define mkdir(path,mode) _mkdir (path)
109 #define link(old,neu) (CreateHardLink (neu, old, 0) ? 0 : EIO_ERRNO (ENOENT, -1))
110
111 #define chown(path,uid,gid) EIO_ENOSYS ()
112 #define fchown(fd,uid,gid) EIO_ENOSYS ()
113 #define truncate(path,offs) EIO_ENOSYS () /* far-miss: SetEndOfFile */
114 #define ftruncate(fd,offs) EIO_ENOSYS () /* near-miss: SetEndOfFile */
115 #define mknod(path,mode,dev) EIO_ENOSYS ()
116 #define sync() EIO_ENOSYS ()
117
118 /* we could even stat and see if it exists */
119 static int
120 symlink (const char *old, const char *neu)
121 {
122 if (CreateSymbolicLink (neu, old, 1))
123 return 0;
124
125 if (CreateSymbolicLink (neu, old, 0))
126 return 0;
127
128 return EIO_ERRNO (ENOENT, -1);
129 }
130
91#else 131#else
92 132
93# include <sys/time.h> 133 #include <sys/time.h>
94# include <sys/select.h> 134 #include <sys/select.h>
135 #include <sys/statvfs.h>
95# include <unistd.h> 136 #include <unistd.h>
96# include <utime.h> 137 #include <utime.h>
97# include <signal.h> 138 #include <signal.h>
98# include <dirent.h> 139 #include <dirent.h>
99 140
100#if _POSIX_MEMLOCK || _POSIX_MEMLOCK_RANGE || _POSIX_MAPPED_FILES 141 #if _POSIX_MEMLOCK || _POSIX_MEMLOCK_RANGE || _POSIX_MAPPED_FILES
101# include <sys/mman.h> 142 #include <sys/mman.h>
102#endif 143 #endif
103 144
104/* POSIX_SOURCE is useless on bsd's, and XOPEN_SOURCE is unreliable there, too */ 145 /* POSIX_SOURCE is useless on bsd's, and XOPEN_SOURCE is unreliable there, too */
105# if __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ 146 #if __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__
106# define _DIRENT_HAVE_D_TYPE /* sigh */ 147 #define _DIRENT_HAVE_D_TYPE /* sigh */
107# define D_INO(de) (de)->d_fileno 148 #define D_INO(de) (de)->d_fileno
108# define D_NAMLEN(de) (de)->d_namlen 149 #define D_NAMLEN(de) (de)->d_namlen
109# elif __linux || defined d_ino || _XOPEN_SOURCE >= 600 150 #elif __linux || defined d_ino || _XOPEN_SOURCE >= 600
110# define D_INO(de) (de)->d_ino 151 #define D_INO(de) (de)->d_ino
111# endif 152 #endif
112 153
113#ifdef _D_EXACT_NAMLEN 154 #ifdef _D_EXACT_NAMLEN
114# undef D_NAMLEN 155 #undef D_NAMLEN
115# define D_NAMLEN(de) _D_EXACT_NAMLEN (de) 156 #define D_NAMLEN(de) _D_EXACT_NAMLEN (de)
116#endif 157 #endif
117 158
118# ifdef _DIRENT_HAVE_D_TYPE 159 #ifdef _DIRENT_HAVE_D_TYPE
119# define D_TYPE(de) (de)->d_type 160 #define D_TYPE(de) (de)->d_type
120# endif 161 #endif
121 162
122# ifndef EIO_STRUCT_DIRENT 163 #ifndef EIO_STRUCT_DIRENT
123# define EIO_STRUCT_DIRENT struct dirent 164 #define EIO_STRUCT_DIRENT struct dirent
124# endif 165 #endif
125 166
126#endif 167#endif
127 168
128#if HAVE_SENDFILE 169#if HAVE_SENDFILE
129# if __linux 170# if __linux
381} 422}
382 423
383static void ecb_cold 424static void ecb_cold
384etp_thread_init (void) 425etp_thread_init (void)
385{ 426{
427#if !HAVE_PREADWRITE
428 X_MUTEX_CREATE (preadwritelock);
429#endif
386 X_MUTEX_CREATE (wrklock); 430 X_MUTEX_CREATE (wrklock);
387 X_MUTEX_CREATE (reslock); 431 X_MUTEX_CREATE (reslock);
388 X_MUTEX_CREATE (reqlock); 432 X_MUTEX_CREATE (reqlock);
389 X_COND_CREATE (reqwait); 433 X_COND_CREATE (reqwait);
390} 434}
391 435
392static void ecb_cold 436static void ecb_cold
393etp_atfork_prepare (void) 437etp_atfork_prepare (void)
394{ 438{
395 X_LOCK (wrklock);
396 X_LOCK (reqlock);
397 X_LOCK (reslock);
398#if !HAVE_PREADWRITE
399 X_LOCK (preadwritelock);
400#endif
401} 439}
402 440
403static void ecb_cold 441static void ecb_cold
404etp_atfork_parent (void) 442etp_atfork_parent (void)
405{ 443{
406#if !HAVE_PREADWRITE
407 X_UNLOCK (preadwritelock);
408#endif
409 X_UNLOCK (reslock);
410 X_UNLOCK (reqlock);
411 X_UNLOCK (wrklock);
412} 444}
413 445
414static void ecb_cold 446static void ecb_cold
415etp_atfork_child (void) 447etp_atfork_child (void)
416{ 448{
845# undef pread 877# undef pread
846# undef pwrite 878# undef pwrite
847# define pread eio__pread 879# define pread eio__pread
848# define pwrite eio__pwrite 880# define pwrite eio__pwrite
849 881
850static ssize_t 882static eio_ssize_t
851eio__pread (int fd, void *buf, size_t count, off_t offset) 883eio__pread (int fd, void *buf, size_t count, off_t offset)
852{ 884{
853 ssize_t res; 885 eio_ssize_t res;
854 off_t ooffset; 886 off_t ooffset;
855 887
856 X_LOCK (preadwritelock); 888 X_LOCK (preadwritelock);
857 ooffset = lseek (fd, 0, SEEK_CUR); 889 ooffset = lseek (fd, 0, SEEK_CUR);
858 lseek (fd, offset, SEEK_SET); 890 lseek (fd, offset, SEEK_SET);
861 X_UNLOCK (preadwritelock); 893 X_UNLOCK (preadwritelock);
862 894
863 return res; 895 return res;
864} 896}
865 897
866static ssize_t 898static eio_ssize_t
867eio__pwrite (int fd, void *buf, size_t count, off_t offset) 899eio__pwrite (int fd, void *buf, size_t count, off_t offset)
868{ 900{
869 ssize_t res; 901 eio_ssize_t res;
870 off_t ooffset; 902 off_t ooffset;
871 903
872 X_LOCK (preadwritelock); 904 X_LOCK (preadwritelock);
873 ooffset = lseek (fd, 0, SEEK_CUR); 905 ooffset = lseek (fd, 0, SEEK_CUR);
874 lseek (fd, offset, SEEK_SET); 906 lseek (fd, offset, SEEK_SET);
963 995
964#if !HAVE_READAHEAD 996#if !HAVE_READAHEAD
965# undef readahead 997# undef readahead
966# define readahead(fd,offset,count) eio__readahead (fd, offset, count, self) 998# define readahead(fd,offset,count) eio__readahead (fd, offset, count, self)
967 999
968static ssize_t 1000static eio_ssize_t
969eio__readahead (int fd, off_t offset, size_t count, etp_worker *self) 1001eio__readahead (int fd, off_t offset, size_t count, etp_worker *self)
970{ 1002{
971 size_t todo = count; 1003 size_t todo = count;
972 dBUF; 1004 dBUF;
973 1005
985} 1017}
986 1018
987#endif 1019#endif
988 1020
989/* sendfile always needs emulation */ 1021/* sendfile always needs emulation */
990static ssize_t 1022static eio_ssize_t
991eio__sendfile (int ofd, int ifd, off_t offset, size_t count, etp_worker *self) 1023eio__sendfile (int ofd, int ifd, off_t offset, size_t count, etp_worker *self)
992{ 1024{
993 ssize_t written = 0; 1025 eio_ssize_t written = 0;
994 ssize_t res; 1026 eio_ssize_t res;
995 1027
996 if (!count) 1028 if (!count)
997 return 0; 1029 return 0;
998 1030
999 for (;;) 1031 for (;;)
1051 if (res < 0 && sbytes) 1083 if (res < 0 && sbytes)
1052 res = sbytes; 1084 res = sbytes;
1053 1085
1054# endif 1086# endif
1055 1087
1056#elif defined (_WIN32) 1088#elif defined (_WIN32) && 0
1057 /* does not work, just for documentation of what would need to be done */ 1089 /* does not work, just for documentation of what would need to be done */
1058 /* actually, cannot be done like this, as TransmitFile changes the file offset, */ 1090 /* actually, cannot be done like this, as TransmitFile changes the file offset, */
1059 /* libeio guarantees that the file offset does not change, and windows */ 1091 /* libeio guarantees that the file offset does not change, and windows */
1060 /* has no way to get an independent handle to the same file description */ 1092 /* has no way to get an independent handle to the same file description */
1061 HANDLE h = TO_SOCKET (ifd); 1093 HANDLE h = TO_SOCKET (ifd);
1108 1140
1109 res = 0; 1141 res = 0;
1110 1142
1111 while (count) 1143 while (count)
1112 { 1144 {
1113 ssize_t cnt; 1145 eio_ssize_t cnt;
1114 1146
1115 cnt = pread (ifd, eio_buf, count > EIO_BUFSIZE ? EIO_BUFSIZE : count, offset); 1147 cnt = pread (ifd, eio_buf, count > EIO_BUFSIZE ? EIO_BUFSIZE : count, offset);
1116 1148
1117 if (cnt <= 0) 1149 if (cnt <= 0)
1118 { 1150 {
1166 /* round up length */ 1198 /* round up length */
1167 *length = (*length + mask) & ~mask; 1199 *length = (*length + mask) & ~mask;
1168} 1200}
1169 1201
1170#if !_POSIX_MEMLOCK 1202#if !_POSIX_MEMLOCK
1171# define eio__mlockall(a) ((errno = ENOSYS), -1) 1203# define eio__mlockall(a) EIO_ENOSYS ()
1172#else 1204#else
1173 1205
1174static int 1206static int
1175eio__mlockall (int flags) 1207eio__mlockall (int flags)
1176{ 1208{
1190 return mlockall (flags); 1222 return mlockall (flags);
1191} 1223}
1192#endif 1224#endif
1193 1225
1194#if !_POSIX_MEMLOCK_RANGE 1226#if !_POSIX_MEMLOCK_RANGE
1195# define eio__mlock(a,b) ((errno = ENOSYS), -1) 1227# define eio__mlock(a,b) EIO_ENOSYS ()
1196#else 1228#else
1197 1229
1198static int 1230static int
1199eio__mlock (void *addr, size_t length) 1231eio__mlock (void *addr, size_t length)
1200{ 1232{
1204} 1236}
1205 1237
1206#endif 1238#endif
1207 1239
1208#if !(_POSIX_MAPPED_FILES && _POSIX_SYNCHRONIZED_IO) 1240#if !(_POSIX_MAPPED_FILES && _POSIX_SYNCHRONIZED_IO)
1209# define eio__msync(a,b,c) ((errno = ENOSYS), -1) 1241# define eio__msync(a,b,c) EIO_ENOSYS ()
1210#else 1242#else
1211 1243
1212static int 1244static int
1213eio__msync (void *mem, size_t len, int flags) 1245eio__msync (void *mem, size_t len, int flags)
1214{ 1246{
1326 res += strlen (res); 1358 res += strlen (res);
1327 } 1359 }
1328 1360
1329 while (*rel) 1361 while (*rel)
1330 { 1362 {
1331 ssize_t len, linklen; 1363 eio_ssize_t len, linklen;
1332 char *beg = rel; 1364 char *beg = rel;
1333 1365
1334 while (*rel && *rel != '/') 1366 while (*rel && *rel != '/')
1335 ++rel; 1367 ++rel;
1336 1368
1803X_THREAD_PROC (etp_proc) 1835X_THREAD_PROC (etp_proc)
1804{ 1836{
1805 ETP_REQ *req; 1837 ETP_REQ *req;
1806 struct timespec ts; 1838 struct timespec ts;
1807 etp_worker *self = (etp_worker *)thr_arg; 1839 etp_worker *self = (etp_worker *)thr_arg;
1840 int timeout;
1808 1841
1809 /* try to distribute timeouts somewhat randomly */ 1842 /* try to distribute timeouts somewhat evenly */
1810 ts.tv_nsec = ((unsigned long)self & 1023UL) * (1000000000UL / 1024UL); 1843 ts.tv_nsec = ((unsigned long)self & 1023UL) * (1000000000UL / 1024UL);
1811 1844
1812 for (;;) 1845 for (;;)
1813 { 1846 {
1847 ts.tv_sec = 0;
1848
1814 X_LOCK (reqlock); 1849 X_LOCK (reqlock);
1815 1850
1816 for (;;) 1851 for (;;)
1817 { 1852 {
1818 self->req = req = reqq_shift (&req_queue); 1853 self->req = req = reqq_shift (&req_queue);
1819 1854
1820 if (req) 1855 if (req)
1821 break; 1856 break;
1822 1857
1858 if (ts.tv_sec == 1) /* no request, but timeout detected, let's quit */
1859 {
1860 X_UNLOCK (reqlock);
1861 X_LOCK (wrklock);
1862 --started;
1863 X_UNLOCK (wrklock);
1864 goto quit;
1865 }
1866
1823 ++idle; 1867 ++idle;
1824 1868
1825 ts.tv_sec = time (0) + idle_timeout; 1869 if (idle <= max_idle)
1826 if (X_COND_TIMEDWAIT (reqwait, reqlock, ts) == ETIMEDOUT) 1870 /* we are allowed to idle, so do so without any timeout */
1871 X_COND_WAIT (reqwait, reqlock);
1872 else
1827 { 1873 {
1828 if (idle > max_idle) 1874 /* initialise timeout once */
1829 { 1875 if (!ts.tv_sec)
1830 --idle; 1876 ts.tv_sec = time (0) + idle_timeout;
1831 X_UNLOCK (reqlock);
1832 X_LOCK (wrklock);
1833 --started;
1834 X_UNLOCK (wrklock);
1835 goto quit;
1836 }
1837 1877
1838 /* we are allowed to idle, so do so without any timeout */
1839 X_COND_WAIT (reqwait, reqlock); 1878 if (X_COND_TIMEDWAIT (reqwait, reqlock, ts) == ETIMEDOUT)
1879 ts.tv_sec = 1; /* assuming this is not a value computed above.,.. */
1840 } 1880 }
1841 1881
1842 --idle; 1882 --idle;
1843 } 1883 }
1844 1884
2139eio_req *eio_fchmod (int fd, mode_t mode, int pri, eio_cb cb, void *data) 2179eio_req *eio_fchmod (int fd, mode_t mode, int pri, eio_cb cb, void *data)
2140{ 2180{
2141 REQ (EIO_FCHMOD); req->int1 = fd; req->int2 = (long)mode; SEND; 2181 REQ (EIO_FCHMOD); req->int1 = fd; req->int2 = (long)mode; SEND;
2142} 2182}
2143 2183
2144eio_req *eio_fchown (int fd, uid_t uid, gid_t gid, int pri, eio_cb cb, void *data) 2184eio_req *eio_fchown (int fd, eio_uid_t uid, eio_gid_t gid, int pri, eio_cb cb, void *data)
2145{ 2185{
2146 REQ (EIO_FCHOWN); req->int1 = fd; req->int2 = (long)uid; req->int3 = (long)gid; SEND; 2186 REQ (EIO_FCHOWN); req->int1 = fd; req->int2 = (long)uid; req->int3 = (long)gid; SEND;
2147} 2187}
2148 2188
2149eio_req *eio_dup2 (int fd, int fd2, int pri, eio_cb cb, void *data) 2189eio_req *eio_dup2 (int fd, int fd2, int pri, eio_cb cb, void *data)
2169eio_req *eio_truncate (const char *path, off_t offset, int pri, eio_cb cb, void *data) 2209eio_req *eio_truncate (const char *path, off_t offset, int pri, eio_cb cb, void *data)
2170{ 2210{
2171 REQ (EIO_TRUNCATE); PATH; req->offs = offset; SEND; 2211 REQ (EIO_TRUNCATE); PATH; req->offs = offset; SEND;
2172} 2212}
2173 2213
2174eio_req *eio_chown (const char *path, uid_t uid, gid_t gid, int pri, eio_cb cb, void *data) 2214eio_req *eio_chown (const char *path, eio_uid_t uid, eio_gid_t gid, int pri, eio_cb cb, void *data)
2175{ 2215{
2176 REQ (EIO_CHOWN); PATH; req->int2 = (long)uid; req->int3 = (long)gid; SEND; 2216 REQ (EIO_CHOWN); PATH; req->int2 = (long)uid; req->int3 = (long)gid; SEND;
2177} 2217}
2178 2218
2179eio_req *eio_chmod (const char *path, mode_t mode, int pri, eio_cb cb, void *data) 2219eio_req *eio_chmod (const char *path, mode_t mode, int pri, eio_cb cb, void *data)
2326} 2366}
2327 2367
2328/*****************************************************************************/ 2368/*****************************************************************************/
2329/* misc garbage */ 2369/* misc garbage */
2330 2370
2331ssize_t 2371eio_ssize_t
2332eio_sendfile_sync (int ofd, int ifd, off_t offset, size_t count) 2372eio_sendfile_sync (int ofd, int ifd, off_t offset, size_t count)
2333{ 2373{
2334 etp_worker wrk; 2374 etp_worker wrk;
2335 ssize_t ret; 2375 eio_ssize_t ret;
2336 2376
2337 wrk.dbuf = 0; 2377 wrk.dbuf = 0;
2338 2378
2339 ret = eio__sendfile (ofd, ifd, offset, count, &wrk); 2379 ret = eio__sendfile (ofd, ifd, offset, count, &wrk);
2340 2380

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines