Fix: poll compat layer reallocation new size
authorDavid Goulet <dgoulet@efficios.com>
Thu, 6 Jun 2013 19:30:14 +0000 (15:30 -0400)
committerDavid Goulet <dgoulet@efficios.com>
Thu, 6 Jun 2013 19:43:25 +0000 (15:43 -0400)
The size was doubled but in fact it should have been checked for the
maximum between the number of fd doubled and the alloc size doubled
(divised by two when shrinking the buffer).

Same goes for the shrink process. For that, get_count_order_u32() is
added to utils.c/.h.

Signed-off-by: David Goulet <dgoulet@efficios.com>
src/common/compat/compat-epoll.c
src/common/compat/compat-poll.c
src/common/utils.c
src/common/utils.h

index f014a0d783d434f57fc95a5c17e126f62946e74e..903a9f8256eeafad9e678f565ba6c1b60f0e9c2a 100644 (file)
@@ -27,6 +27,8 @@
 
 #include <common/error.h>
 #include <common/defaults.h>
+#include <common/macros.h>
+#include <common/utils.h>
 
 #include "poll.h"
 
@@ -201,11 +203,15 @@ int compat_epoll_wait(struct lttng_poll_event *events, int timeout)
         */
        if (events->nb_fd > events->alloc_size) {
                /* Expand if the nb_fd is higher than the actual size. */
-               new_size = events->alloc_size << 1UL;
+               new_size = max_t(uint32_t,
+                               1U << utils_get_count_order_u32(events->nb_fd),
+                               events->alloc_size << 1UL);
        } else if ((events->nb_fd << 1UL) <= events->alloc_size &&
                        events->nb_fd >= events->init_size) {
                /* Shrink if nb_fd multiplied by two is <= than the actual size. */
-               new_size = events->alloc_size >> 1UL;
+               new_size = max_t(uint32_t,
+                               utils_get_count_order_u32(events->nb_fd) >> 1U,
+                               events->alloc_size >> 1U);
        } else {
                /* Indicate that we don't want to resize. */
                new_size = 0;
index bc79eed0aaa5321c48fcd055858698bcdc5fa375..79fcb7d652b87230815c4d7b6d7146cf8546a9c2 100644 (file)
@@ -23,6 +23,8 @@
 
 #include <common/defaults.h>
 #include <common/error.h>
+#include <common/macros.h>
+#include <common/utils.h>
 
 #include "poll.h"
 
@@ -168,7 +170,9 @@ int compat_poll_add(struct lttng_poll_event *events, int fd,
        /* Check for a needed resize of the array. */
        if (current->nb_fd > current->alloc_size) {
                /* Expand it by a power of two of the current size. */
-               new_size = current->alloc_size << 1UL;
+               new_size = max_t(int,
+                               1U << utils_get_count_order_u32(current->nb_fd),
+                               current->alloc_size << 1UL);
                ret = resize_poll_event(current, new_size);
                if (ret < 0) {
                        goto error;
@@ -212,7 +216,9 @@ int compat_poll_del(struct lttng_poll_event *events, int fd)
                 * Shrink if nb_fd multiplied by two is <= than the actual size and we
                 * are above the initial size.
                 */
-               new_size = current->alloc_size >> 1UL;
+               new_size = max_t(int,
+                               utils_get_count_order_u32(current->nb_fd) >> 1U,
+                               current->alloc_size >> 1U);
                ret = resize_poll_event(current, new_size);
                if (ret < 0) {
                        goto error;
index f3718f00fa8ddabb7c921ac55287626dd83f45b8..38f78a7e8e7d40cd6fcebefd297e5bb240c52aaf 100644 (file)
@@ -440,7 +440,7 @@ static void regex_print_error(int errcode, regex_t *regex)
  *
  * @param str  The string to parse.
  * @param size Pointer to a size_t that will be filled with the
- *             resulting size.
+ *             resulting size.
  *
  * @return 0 on success, -1 on failure.
  */
@@ -518,3 +518,69 @@ free:
 end:
        return ret;
 }
+
+/*
+ * fls: returns the position of the most significant bit.
+ * Returns 0 if no bit is set, else returns the position of the most
+ * significant bit (from 1 to 32 on 32-bit, from 1 to 64 on 64-bit).
+ */
+#if defined(__i386) || defined(__x86_64)
+static inline unsigned int fls_u32(uint32_t x)
+{
+       int r;
+
+       asm("bsrl %1,%0\n\t"
+               "jnz 1f\n\t"
+               "movl $-1,%0\n\t"
+               "1:\n\t"
+               : "=r" (r) : "rm" (x));
+       return r + 1;
+}
+#define HAS_FLS_U32
+#endif
+
+#ifndef HAS_FLS_U32
+static __attribute__((unused)) unsigned int fls_u32(uint32_t x)
+{
+       unsigned int r = 32;
+
+       if (!x) {
+               return 0;
+       }
+       if (!(x & 0xFFFF0000U)) {
+               x <<= 16;
+               r -= 16;
+       }
+       if (!(x & 0xFF000000U)) {
+               x <<= 8;
+               r -= 8;
+       }
+       if (!(x & 0xF0000000U)) {
+               x <<= 4;
+               r -= 4;
+       }
+       if (!(x & 0xC0000000U)) {
+               x <<= 2;
+               r -= 2;
+       }
+       if (!(x & 0x80000000U)) {
+               x <<= 1;
+               r -= 1;
+       }
+       return r;
+}
+#endif
+
+/*
+ * Return the minimum order for which x <= (1UL << order).
+ * Return -1 if x is 0.
+ */
+LTTNG_HIDDEN
+int utils_get_count_order_u32(uint32_t x)
+{
+       if (!x) {
+               return -1;
+       }
+
+       return fls_u32(x - 1);
+}
index d8a5321c7c5799e7b706390cacd93b8cd3e4be1f..083acef93a0a784e24f99a9299bddfa42ab23883 100644 (file)
@@ -39,5 +39,6 @@ int utils_create_stream_file(char *path_name, char *file_name, uint64_t size,
 int utils_rotate_stream_file(char *path_name, char *file_name, uint64_t size,
                uint64_t count, int uid, int gid, int out_fd, uint64_t *new_count);
 int utils_parse_size_suffix(char *str, uint64_t *size);
+int utils_get_count_order_u32(uint32_t x);
 
 #endif /* _COMMON_UTILS_H */
This page took 0.029827 seconds and 4 git commands to generate.