summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changes2
-rw-r--r--ecb.h100
-rw-r--r--eio.c3
-rw-r--r--eio.pod2
4 files changed, 49 insertions, 58 deletions
diff --git a/Changes b/Changes
index 8462462..bde7245 100644
--- a/Changes
+++ b/Changes
@@ -7,6 +7,8 @@ TODO: make mtouch/readdir maybe others cancellable in-request
TODO: fadvise request
1.0
- use nonstandard but maybe-working-on-bsd fork technique.
+ - fix a path-memory-leak in readdir when using the wrappers
+ (reported by Thomas L. Shinnick).
- support a max_idle value of 0.
- support setting of idle timeout value (eio_set_idle_timeout).
- readdir: correctly handle malloc failures.
diff --git a/ecb.h b/ecb.h
index d7d8920..515f80d 100644
--- a/ecb.h
+++ b/ecb.h
@@ -40,7 +40,7 @@
#if __GNUC__
typedef signed long long int64_t;
typedef unsigned long long uint64_t;
- #else
+ #else /* _MSC_VER || __BORLANDC__ */
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
#endif
@@ -154,11 +154,19 @@ typedef int ecb_bool;
x &= ~x + 1; /* this isolates the lowest bit */
+#if ECB_branchless_on_i386
+ r += !!(x & 0xaaaaaaaa) << 0;
+ r += !!(x & 0xcccccccc) << 1;
+ r += !!(x & 0xf0f0f0f0) << 2;
+ r += !!(x & 0xff00ff00) << 3;
+ r += !!(x & 0xffff0000) << 4;
+#else
if (x & 0xaaaaaaaa) r += 1;
if (x & 0xcccccccc) r += 2;
if (x & 0xf0f0f0f0) r += 4;
if (x & 0xff00ff00) r += 8;
if (x & 0xffff0000) r += 16;
+#endif
return r;
}
@@ -168,7 +176,7 @@ typedef int ecb_bool;
ecb_ctz64 (uint64_t x)
{
int shift = x & 0xffffffffU ? 0 : 32;
- return ecb_ctz (x >> shift) + shift;
+ return ecb_ctz32 (x >> shift) + shift;
}
ecb_function_ int ecb_popcount32 (uint32_t x) ecb_const;
@@ -189,14 +197,13 @@ typedef int ecb_bool;
ecb_function_ int ecb_ld32 (uint32_t x) ecb_const;
ecb_function_ int ecb_ld32 (uint32_t x)
{
- int r = -1;
+ int r = 0;
- do
- {
- x >>= 1;
- ++r;
- }
- while (x);
+ if (x >> 16) { x >>= 16; r += 16; }
+ if (x >> 8) { x >>= 8; r += 8; }
+ if (x >> 4) { x >>= 4; r += 4; }
+ if (x >> 2) { x >>= 2; r += 2; }
+ if (x >> 1) { r += 1; }
return r;
}
@@ -204,16 +211,11 @@ typedef int ecb_bool;
ecb_function_ int ecb_ld64 (uint64_t x) ecb_const;
ecb_function_ int ecb_ld64 (uint64_t x)
{
- int r = -1;
+ int r = 0;
- do
- {
- x >>= 1;
- ++r;
- }
- while (x);
+ if (x >> 32) { x >>= 32; r += 32; }
- return r;
+ return r + ecb_ld32 (x);
}
#endif
@@ -226,36 +228,48 @@ ecb_popcount64 (uint64_t x)
return ecb_popcount32 (x) + ecb_popcount32 (x >> 32);
}
+ecb_inline uint8_t ecb_rotl8 (uint8_t x, unsigned int count) ecb_const;
+ecb_inline uint8_t ecb_rotr8 (uint8_t x, unsigned int count) ecb_const;
+ecb_inline uint16_t ecb_rotl16 (uint16_t x, unsigned int count) ecb_const;
+ecb_inline uint16_t ecb_rotr16 (uint16_t x, unsigned int count) ecb_const;
+ecb_inline uint32_t ecb_rotl32 (uint32_t x, unsigned int count) ecb_const;
+ecb_inline uint32_t ecb_rotr32 (uint32_t x, unsigned int count) ecb_const;
+ecb_inline uint64_t ecb_rotl64 (uint64_t x, unsigned int count) ecb_const;
+ecb_inline uint64_t ecb_rotr64 (uint64_t x, unsigned int count) ecb_const;
+
+ecb_inline uint8_t ecb_rotl8 (uint8_t x, unsigned int count) { return (x >> ( 8 - count)) | (x << count); }
+ecb_inline uint8_t ecb_rotr8 (uint8_t x, unsigned int count) { return (x << ( 8 - count)) | (x >> count); }
+ecb_inline uint16_t ecb_rotl16 (uint16_t x, unsigned int count) { return (x >> (16 - count)) | (x << count); }
+ecb_inline uint16_t ecb_rotr16 (uint16_t x, unsigned int count) { return (x << (16 - count)) | (x >> count); }
+ecb_inline uint32_t ecb_rotl32 (uint32_t x, unsigned int count) { return (x >> (32 - count)) | (x << count); }
+ecb_inline uint32_t ecb_rotr32 (uint32_t x, unsigned int count) { return (x << (32 - count)) | (x >> count); }
+ecb_inline uint64_t ecb_rotl64 (uint64_t x, unsigned int count) { return (x >> (64 - count)) | (x << count); }
+ecb_inline uint64_t ecb_rotr64 (uint64_t x, unsigned int count) { return (x << (64 - count)) | (x >> count); }
+
#if ECB_GCC_VERSION(4,3)
#define ecb_bswap16(x) (__builtin_bswap32 (x) >> 16)
#define ecb_bswap32(x) __builtin_bswap32 (x)
#define ecb_bswap64(x) __builtin_bswap64 (x)
#else
- ecb_function_ uint32_t ecb_bswap16 (uint32_t x) ecb_const;
- ecb_function_ uint32_t
- ecb_bswap16 (uint32_t x)
+ ecb_function_ uint16_t ecb_bswap16 (uint16_t x) ecb_const;
+ ecb_function_ uint16_t
+ ecb_bswap16 (uint16_t x)
{
- return ((x >> 8) & 0xff)
- | ((x << 8) & 0x00ff0000)
- | (x << 24);
+ return ecb_rotl16 (x, 8);
}
ecb_function_ uint32_t ecb_bswap32 (uint32_t x) ecb_const;
ecb_function_ uint32_t
ecb_bswap32 (uint32_t x)
{
- return (x >> 24)
- | ((x >> 8) & 0x0000ff00)
- | ((x << 8) & 0x00ff0000)
- | (x << 24);
+ return (((uint32_t)ecb_bswap16 (x)) << 16) | ecb_bswap16 (x >> 16);
}
ecb_function_ uint64_t ecb_bswap64 (uint64_t x) ecb_const;
ecb_function_ uint64_t
ecb_bswap64 (uint64_t x)
{
- return (((uint64_t)ecb_bswap32 (x)) << 32)
- | ecb_bswap32 (x >> 32);
+ return (((uint64_t)ecb_bswap32 (x)) << 32) | ecb_bswap32 (x >> 32);
}
#endif
@@ -300,33 +314,5 @@ ecb_function_ ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper ()
#define ecb_array_length(name) (sizeof (name) / sizeof (name [0]))
#endif
-ecb_inline uint32_t ecb_rotr32 (uint32_t x, unsigned int count) ecb_const;
-ecb_inline uint32_t
-ecb_rotr32 (uint32_t x, unsigned int count)
-{
- return (x << (32 - count)) | (x >> count);
-}
-
-ecb_inline uint32_t ecb_rotl32 (uint32_t x, unsigned int count) ecb_const;
-ecb_inline uint32_t
-ecb_rotl32 (uint32_t x, unsigned int count)
-{
- return (x >> (32 - count)) | (x << count);
-}
-
-ecb_inline uint64_t ecb_rotr64 (uint64_t x, unsigned int count) ecb_const;
-ecb_inline uint64_t
-ecb_rotr64 (uint64_t x, unsigned int count)
-{
- return (x << (64 - count)) | (x >> count);
-}
-
-ecb_inline uint64_t ecb_rotl64 (uint64_t x, unsigned int count) ecb_const;
-ecb_inline uint64_t
-ecb_rotl64 (uint64_t x, unsigned int count)
-{
- return (x >> (64 - count)) | (x << count);
-}
-
#endif
diff --git a/eio.c b/eio.c
index a191ed8..2ee77c7 100644
--- a/eio.c
+++ b/eio.c
@@ -1308,6 +1308,9 @@ eio__scandir (eio_req *req, etp_worker *self)
/* the corresponding closedir is in ETP_WORKER_CLEAR */
self->dirp = dirp = opendir (req->ptr1);
+ if (req->flags & EIO_FLAG_PTR1_FREE)
+ free (req->ptr1);
+
req->flags |= EIO_FLAG_PTR1_FREE | EIO_FLAG_PTR2_FREE;
req->ptr1 = dents = flags ? malloc (dentalloc * sizeof (eio_dirent)) : 0;
req->ptr2 = names = malloc (namesalloc);
diff --git a/eio.pod b/eio.pod
index f20af11..c55f1e8 100644
--- a/eio.pod
+++ b/eio.pod
@@ -228,7 +228,7 @@ custom data value as C<data>.
=head3 POSIX API WRAPPERS
These requests simply wrap the POSIX call of the same name, with the same
-arguments. If a function is not implemented by the OS and cnanot be emulated
+arguments. If a function is not implemented by the OS and cannot be emulated
in some way, then all of these return C<-1> and set C<errorno> to C<ENOSYS>.
=over 4