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

Comparing libeio/eio.c (file contents):
Revision 1.72 by root, Fri Jun 10 12:45:20 2011 UTC vs.
Revision 1.77 by root, Tue Jul 5 14:02:15 2011 UTC

200/*****************************************************************************/ 200/*****************************************************************************/
201 201
202#define ETP_NUM_PRI (ETP_PRI_MAX - ETP_PRI_MIN + 1) 202#define ETP_NUM_PRI (ETP_PRI_MAX - ETP_PRI_MIN + 1)
203 203
204/* calculate time difference in ~1/EIO_TICKS of a second */ 204/* calculate time difference in ~1/EIO_TICKS of a second */
205ECB_INLINE int 205ecb_inline int
206tvdiff (struct timeval *tv1, struct timeval *tv2) 206tvdiff (struct timeval *tv1, struct timeval *tv2)
207{ 207{
208 return (tv2->tv_sec - tv1->tv_sec ) * EIO_TICKS 208 return (tv2->tv_sec - tv1->tv_sec ) * EIO_TICKS
209 + ((tv2->tv_usec - tv1->tv_usec) >> 10); 209 + ((tv2->tv_usec - tv1->tv_usec) >> 10);
210} 210}
1006 1006
1007 /* according to source inspection, this is correct, and useful behaviour */ 1007 /* according to source inspection, this is correct, and useful behaviour */
1008 if (sbytes) 1008 if (sbytes)
1009 res = sbytes; 1009 res = sbytes;
1010 1010
1011# elif defined (__APPLE__) 1011# elif defined (__APPLE__) && 0 /* broken, as everything on os x */
1012 off_t sbytes = count; 1012 off_t sbytes = count;
1013 res = sendfile (ifd, ofd, offset, &sbytes, 0, 0); 1013 res = sendfile (ifd, ofd, offset, &sbytes, 0, 0);
1014 1014
1015 /* according to the manpage, sbytes is always valid */ 1015 /* according to the manpage, sbytes is always valid */
1016 if (sbytes) 1016 if (sbytes)
1115 count -= cnt; 1115 count -= cnt;
1116 } 1116 }
1117 } 1117 }
1118 1118
1119 return res; 1119 return res;
1120}
1121
1122#ifdef PAGESIZE
1123# define eio_pagesize() PAGESIZE
1124#else
1125static intptr_t
1126eio_pagesize (void)
1127{
1128 static intptr_t page;
1129
1130 if (!page)
1131 page = sysconf (_SC_PAGESIZE);
1132
1133 return page;
1134}
1135#endif
1136
1137static void
1138eio_page_align (void **addr, size_t *length)
1139{
1140 intptr_t mask = eio_pagesize () - 1;
1141
1142 /* round down addr */
1143 intptr_t adj = mask & (intptr_t)*addr;
1144
1145 *addr = (void *)((intptr_t)*addr - adj);
1146 *length += adj;
1147
1148 /* round up length */
1149 *length = (*length + mask) & ~mask;
1150}
1151
1152#if !_POSIX_MEMLOCK
1153# define eio__mlockall(a) ((errno = ENOSYS), -1)
1154#else
1155
1156static int
1157eio__mlockall (int flags)
1158{
1159 #if __GLIBC__ == 2 && __GLIBC_MINOR__ <= 7
1160 extern int mallopt (int, int);
1161 mallopt (-6, 238); /* http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=473812 */
1162 #endif
1163
1164 if (EIO_MCL_CURRENT != MCL_CURRENT
1165 || EIO_MCL_FUTURE != MCL_FUTURE)
1166 {
1167 flags = 0
1168 | (flags & EIO_MCL_CURRENT ? MCL_CURRENT : 0)
1169 | (flags & EIO_MCL_FUTURE ? MCL_FUTURE : 0);
1170 }
1171
1172 return mlockall (flags);
1173}
1174#endif
1175
1176#if !_POSIX_MEMLOCK_RANGE
1177# define eio__mlock(a,b) ((errno = ENOSYS), -1)
1178#else
1179
1180static int
1181eio__mlock (void *addr, size_t length)
1182{
1183 eio_page_align (&addr, &length);
1184
1185 return mlock (addr, length);
1186}
1187
1188#endif
1189
1190#if !(_POSIX_MAPPED_FILES && _POSIX_SYNCHRONIZED_IO)
1191# define eio__msync(a,b,c) ((errno = ENOSYS), -1)
1192#else
1193
1194static int
1195eio__msync (void *mem, size_t len, int flags)
1196{
1197 eio_page_align (&mem, &len);
1198
1199 if (EIO_MS_ASYNC != MS_SYNC
1200 || EIO_MS_INVALIDATE != MS_INVALIDATE
1201 || EIO_MS_SYNC != MS_SYNC)
1202 {
1203 flags = 0
1204 | (flags & EIO_MS_ASYNC ? MS_ASYNC : 0)
1205 | (flags & EIO_MS_INVALIDATE ? MS_INVALIDATE : 0)
1206 | (flags & EIO_MS_SYNC ? MS_SYNC : 0);
1207 }
1208
1209 return msync (mem, len, flags);
1210}
1211
1212#endif
1213
1214static int
1215eio__mtouch (eio_req *req)
1216{
1217 void *mem = req->ptr2;
1218 size_t len = req->size;
1219 int flags = req->int1;
1220
1221 eio_page_align (&mem, &len);
1222
1223 {
1224 intptr_t addr = (intptr_t)mem;
1225 intptr_t end = addr + len;
1226 intptr_t page = eio_pagesize ();
1227
1228 if (addr < end)
1229 if (flags & EIO_MT_MODIFY) /* modify */
1230 do { *((volatile sig_atomic_t *)addr) |= 0; } while ((addr += page) < len && !EIO_CANCELLED (req));
1231 else
1232 do { *((volatile sig_atomic_t *)addr) ; } while ((addr += page) < len && !EIO_CANCELLED (req));
1233 }
1234
1235 return 0;
1236}
1237
1238/*****************************************************************************/
1239/* requests implemented outside eio_execute, because they are so large */
1240
1241static void
1242eio__realpath (eio_req *req, etp_worker *self)
1243{
1244 char *rel = req->ptr1;
1245 char *res;
1246 char *tmp1, *tmp2;
1247#if SYMLOOP_MAX > 32
1248 int links = SYMLOOP_MAX;
1249#else
1250 int links = 32;
1251#endif
1252
1253 req->result = -1;
1254
1255 errno = EINVAL;
1256 if (!rel)
1257 return;
1258
1259 errno = ENOENT;
1260 if (!*rel)
1261 return;
1262
1263 if (!req->ptr2)
1264 {
1265 X_LOCK (wrklock);
1266 req->flags |= EIO_FLAG_PTR2_FREE;
1267 X_UNLOCK (wrklock);
1268 req->ptr2 = malloc (PATH_MAX * 3);
1269
1270 errno = ENOMEM;
1271 if (!req->ptr2)
1272 return;
1273 }
1274
1275 res = req->ptr2;
1276 tmp1 = res + PATH_MAX;
1277 tmp2 = tmp1 + PATH_MAX;
1278
1279 if (*rel != '/')
1280 {
1281 if (!getcwd (res, PATH_MAX))
1282 return;
1283
1284 if (res [1]) /* only use if not / */
1285 res += strlen (res);
1286 }
1287
1288 while (*rel)
1289 {
1290 ssize_t len, linklen;
1291 char *beg = rel;
1292
1293 while (*rel && *rel != '/')
1294 ++rel;
1295
1296 len = rel - beg;
1297
1298 if (!len) /* skip slashes */
1299 {
1300 ++rel;
1301 continue;
1302 }
1303
1304 if (beg [0] == '.')
1305 {
1306 if (len == 1)
1307 continue; /* . - nop */
1308
1309 if (beg [1] == '.' && len == 2)
1310 {
1311 /* .. - back up one component, if possible */
1312
1313 while (res != req->ptr2)
1314 if (*--res == '/')
1315 break;
1316
1317 continue;
1318 }
1319 }
1320
1321 errno = ENAMETOOLONG;
1322 if (res + 1 + len + 1 >= tmp1)
1323 return;
1324
1325 /* copy one component */
1326 *res = '/';
1327 memcpy (res + 1, beg, len);
1328
1329 /* zero-terminate, for readlink */
1330 res [len + 1] = 0;
1331
1332 /* now check if it's a symlink */
1333 linklen = readlink (req->ptr2, tmp1, PATH_MAX);
1334
1335 if (linklen < 0)
1336 {
1337 if (errno != EINVAL)
1338 return;
1339
1340 /* it's a normal directory. hopefully */
1341 res += len + 1;
1342 }
1343 else
1344 {
1345 /* yay, it was a symlink - build new path in tmp2 */
1346 int rellen = strlen (rel);
1347
1348 errno = ENAMETOOLONG;
1349 if (linklen + 1 + rellen >= PATH_MAX)
1350 return;
1351
1352 if (*tmp1 == '/')
1353 res = req->ptr2; /* symlink resolves to an absolute path */
1354
1355 /* we need to be careful, as rel might point into tmp2 already */
1356 memmove (tmp2 + linklen + 1, rel, rellen + 1);
1357 tmp2 [linklen] = '/';
1358 memcpy (tmp2, tmp1, linklen);
1359
1360 rel = tmp2;
1361 }
1362 }
1363
1364 /* special case for the lone root path */
1365 if (res == req->ptr2)
1366 *res++ = '/';
1367
1368 req->result = res - (char *)req->ptr2;
1369 req->ptr2 = realloc (req->ptr2, req->result); /* trade time for space savings */
1120} 1370}
1121 1371
1122static signed char 1372static signed char
1123eio_dent_cmp (const eio_dirent *a, const eio_dirent *b) 1373eio_dent_cmp (const eio_dirent *a, const eio_dirent *b)
1124{ 1374{
1305 flags &= ~(EIO_READDIR_DIRS_FIRST | EIO_READDIR_STAT_ORDER); 1555 flags &= ~(EIO_READDIR_DIRS_FIRST | EIO_READDIR_STAT_ORDER);
1306 1556
1307 X_LOCK (wrklock); 1557 X_LOCK (wrklock);
1308 /* the corresponding closedir is in ETP_WORKER_CLEAR */ 1558 /* the corresponding closedir is in ETP_WORKER_CLEAR */
1309 self->dirp = dirp = opendir (req->ptr1); 1559 self->dirp = dirp = opendir (req->ptr1);
1560
1561 if (req->flags & EIO_FLAG_PTR1_FREE)
1562 free (req->ptr1);
1310 1563
1311 req->flags |= EIO_FLAG_PTR1_FREE | EIO_FLAG_PTR2_FREE; 1564 req->flags |= EIO_FLAG_PTR1_FREE | EIO_FLAG_PTR2_FREE;
1312 req->ptr1 = dents = flags ? malloc (dentalloc * sizeof (eio_dirent)) : 0; 1565 req->ptr1 = dents = flags ? malloc (dentalloc * sizeof (eio_dirent)) : 0;
1313 req->ptr2 = names = malloc (namesalloc); 1566 req->ptr2 = names = malloc (namesalloc);
1314 X_UNLOCK (wrklock); 1567 X_UNLOCK (wrklock);
1481 break; 1734 break;
1482 } 1735 }
1483 } 1736 }
1484} 1737}
1485 1738
1486#ifdef PAGESIZE
1487# define eio_pagesize() PAGESIZE
1488#else
1489static intptr_t
1490eio_pagesize (void)
1491{
1492 static intptr_t page;
1493
1494 if (!page)
1495 page = sysconf (_SC_PAGESIZE);
1496
1497 return page;
1498}
1499#endif
1500
1501static void
1502eio_page_align (void **addr, size_t *length)
1503{
1504 intptr_t mask = eio_pagesize () - 1;
1505
1506 /* round down addr */
1507 intptr_t adj = mask & (intptr_t)*addr;
1508
1509 *addr = (void *)((intptr_t)*addr - adj);
1510 *length += adj;
1511
1512 /* round up length */
1513 *length = (*length + mask) & ~mask;
1514}
1515
1516#if !_POSIX_MEMLOCK
1517# define eio__mlockall(a) ((errno = ENOSYS), -1)
1518#else
1519
1520static int
1521eio__mlockall (int flags)
1522{
1523 #if __GLIBC__ == 2 && __GLIBC_MINOR__ <= 7
1524 extern int mallopt (int, int);
1525 mallopt (-6, 238); /* http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=473812 */
1526 #endif
1527
1528 if (EIO_MCL_CURRENT != MCL_CURRENT
1529 || EIO_MCL_FUTURE != MCL_FUTURE)
1530 {
1531 flags = 0
1532 | (flags & EIO_MCL_CURRENT ? MCL_CURRENT : 0)
1533 | (flags & EIO_MCL_FUTURE ? MCL_FUTURE : 0);
1534 }
1535
1536 return mlockall (flags);
1537}
1538#endif
1539
1540#if !_POSIX_MEMLOCK_RANGE
1541# define eio__mlock(a,b) ((errno = ENOSYS), -1)
1542#else
1543
1544static int
1545eio__mlock (void *addr, size_t length)
1546{
1547 eio_page_align (&addr, &length);
1548
1549 return mlock (addr, length);
1550}
1551
1552#endif
1553
1554#if !(_POSIX_MAPPED_FILES && _POSIX_SYNCHRONIZED_IO)
1555# define eio__msync(a,b,c) ((errno = ENOSYS), -1)
1556#else
1557
1558static int
1559eio__msync (void *mem, size_t len, int flags)
1560{
1561 eio_page_align (&mem, &len);
1562
1563 if (EIO_MS_ASYNC != MS_SYNC
1564 || EIO_MS_INVALIDATE != MS_INVALIDATE
1565 || EIO_MS_SYNC != MS_SYNC)
1566 {
1567 flags = 0
1568 | (flags & EIO_MS_ASYNC ? MS_ASYNC : 0)
1569 | (flags & EIO_MS_INVALIDATE ? MS_INVALIDATE : 0)
1570 | (flags & EIO_MS_SYNC ? MS_SYNC : 0);
1571 }
1572
1573 return msync (mem, len, flags);
1574}
1575
1576#endif
1577
1578static int
1579eio__mtouch (eio_req *req)
1580{
1581 void *mem = req->ptr2;
1582 size_t len = req->size;
1583 int flags = req->int1;
1584
1585 eio_page_align (&mem, &len);
1586
1587 {
1588 intptr_t addr = (intptr_t)mem;
1589 intptr_t end = addr + len;
1590 intptr_t page = eio_pagesize ();
1591
1592 if (addr < end)
1593 if (flags & EIO_MT_MODIFY) /* modify */
1594 do { *((volatile sig_atomic_t *)addr) |= 0; } while ((addr += page) < len && !EIO_CANCELLED (req));
1595 else
1596 do { *((volatile sig_atomic_t *)addr) ; } while ((addr += page) < len && !EIO_CANCELLED (req));
1597 }
1598
1599 return 0;
1600}
1601
1602/*****************************************************************************/ 1739/*****************************************************************************/
1603 1740
1604#define ALLOC(len) \ 1741#define ALLOC(len) \
1605 if (!req->ptr2) \ 1742 if (!req->ptr2) \
1606 { \ 1743 { \
1695eio_init (void (*want_poll)(void), void (*done_poll)(void)) 1832eio_init (void (*want_poll)(void), void (*done_poll)(void))
1696{ 1833{
1697 return etp_init (want_poll, done_poll); 1834 return etp_init (want_poll, done_poll);
1698} 1835}
1699 1836
1700ECB_INLINE void 1837ecb_inline void
1701eio_api_destroy (eio_req *req) 1838eio_api_destroy (eio_req *req)
1702{ 1839{
1703 free (req); 1840 free (req);
1704} 1841}
1705 1842
1771 case EIO_RENAME: req->result = rename (req->ptr1, req->ptr2); break; 1908 case EIO_RENAME: req->result = rename (req->ptr1, req->ptr2); break;
1772 case EIO_LINK: req->result = link (req->ptr1, req->ptr2); break; 1909 case EIO_LINK: req->result = link (req->ptr1, req->ptr2); break;
1773 case EIO_SYMLINK: req->result = symlink (req->ptr1, req->ptr2); break; 1910 case EIO_SYMLINK: req->result = symlink (req->ptr1, req->ptr2); break;
1774 case EIO_MKNOD: req->result = mknod (req->ptr1, (mode_t)req->int2, (dev_t)req->offs); break; 1911 case EIO_MKNOD: req->result = mknod (req->ptr1, (mode_t)req->int2, (dev_t)req->offs); break;
1775 1912
1913 case EIO_REALPATH: eio__realpath (req, self); break;
1914
1776 case EIO_READLINK: ALLOC (PATH_MAX); 1915 case EIO_READLINK: ALLOC (PATH_MAX);
1777 req->result = readlink (req->ptr1, req->ptr2, PATH_MAX); break; 1916 req->result = readlink (req->ptr1, req->ptr2, PATH_MAX); break;
1778 1917
1779 case EIO_SYNC: req->result = 0; sync (); break; 1918 case EIO_SYNC: req->result = 0; sync (); break;
1780 case EIO_FSYNC: req->result = fsync (req->int1); break; 1919 case EIO_FSYNC: req->result = fsync (req->int1); break;
1997eio_req *eio_readlink (const char *path, int pri, eio_cb cb, void *data) 2136eio_req *eio_readlink (const char *path, int pri, eio_cb cb, void *data)
1998{ 2137{
1999 return eio__1path (EIO_READLINK, path, pri, cb, data); 2138 return eio__1path (EIO_READLINK, path, pri, cb, data);
2000} 2139}
2001 2140
2141eio_req *eio_realpath (const char *path, int pri, eio_cb cb, void *data)
2142{
2143 return eio__1path (EIO_REALPATH, path, pri, cb, data);
2144}
2145
2002eio_req *eio_stat (const char *path, int pri, eio_cb cb, void *data) 2146eio_req *eio_stat (const char *path, int pri, eio_cb cb, void *data)
2003{ 2147{
2004 return eio__1path (EIO_STAT, path, pri, cb, data); 2148 return eio__1path (EIO_STAT, path, pri, cb, data);
2005} 2149}
2006 2150

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines