< prev index next >

src/java.base/linux/native/libnet/linux_close.c

Print this page
rev 13764 : 8150460: (linux|bsd|aix)_close.c: file descriptor table may become large or may not work at all
Reviewed-by:

*** 31,40 **** --- 31,41 ---- #include <sys/socket.h> #include <sys/time.h> #include <sys/resource.h> #include <sys/uio.h> #include <unistd.h> + #include <limits.h> #include <errno.h> #include <sys/poll.h> /* * Stack allocated by thread when doing blocking operation
*** 57,70 **** * Signal to unblock thread */ static int sigWakeup = (__SIGRTMAX - 2); /* ! * The fd table and the number of file descriptors ! */ ! static fdEntry_t *fdTable; ! static int fdCount; /* * Null signal handler */ static void sig_wakeup(int sig) { --- 58,81 ---- * Signal to unblock thread */ static int sigWakeup = (__SIGRTMAX - 2); /* ! * The fd table holds one entry per file descriptor. ! * Note: the number of possible file descriptors can get quite large; ! * RLIMIT_NO_FILE can be large or even infinite. ! * The fd table is organized as sparse two dimensional array, with a ! * root array holding pointers to entry arrays, which in turn hold ! * the entries. entry arrays are allocated on demand, save for the ! * very first one, which is pre-allocated. ! */ ! fdEntry_t** fdTable; ! pthread_mutex_t fdTableLock = PTHREAD_MUTEX_INITIALIZER; ! /* Number of bits to apply to the file descriptor to get the index into ! * the root array resp. entry array */ ! unsigned fdTableRootArrayBits; ! unsigned fdTableEntryArrayBits; /* * Null signal handler */ static void sig_wakeup(int sig) {
*** 74,98 **** * Initialization routine (executed when library is loaded) * Allocate fd tables and sets up signal handler. */ static void __attribute((constructor)) init() { struct rlimit nbr_files; sigset_t sigset; struct sigaction sa; ! /* ! * Allocate table based on the maximum number of ! * file descriptors. ! */ getrlimit(RLIMIT_NOFILE, &nbr_files); ! fdCount = nbr_files.rlim_max; ! fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t)); if (fdTable == NULL) { fprintf(stderr, "library initialization failed - " "unable to allocate file descriptor table - out of memory"); abort(); } /* * Setup the signal handler */ sa.sa_handler = sig_wakeup; --- 85,133 ---- * Initialization routine (executed when library is loaded) * Allocate fd tables and sets up signal handler. */ static void __attribute((constructor)) init() { struct rlimit nbr_files; + unsigned max = 0; + unsigned maxbits; sigset_t sigset; struct sigaction sa; ! /* Determine the maximum number of possible file descriptors. */ getrlimit(RLIMIT_NOFILE, &nbr_files); ! if (nbr_files.rlim_max != RLIM_INFINITY) { ! max = nbr_files.rlim_max; ! } else { ! max = INT_MAX; ! } ! ! /* How many bits do we need to cover all possible values for ! * file descriptors? */ ! for (maxbits = 1; ! (unsigned) 1 << maxbits < max && maxbits < 32; ! maxbits ++); ! ! /* Calculate size of entry arrays: for small possible file descriptor ranges, ! * fall back to a linear array. For larger ranges, make the entry tables 64K. ! * This means for the largest possible range of INT_MAX (32bit ints), the root ! * table will be 32K entries (32K * 64K = INT_MAX) */ ! fdTableEntryArrayBits = maxbits > 16 ? 16 : maxbits; ! fdTableRootArrayBits = maxbits - fdTableEntryArrayBits; ! ! /* Allocate root array */ ! fdTable = (fdEntry_t**)calloc(1 << fdTableRootArrayBits, sizeof(fdEntry_t*)); if (fdTable == NULL) { fprintf(stderr, "library initialization failed - " "unable to allocate file descriptor table - out of memory"); abort(); } + fdTable[0] = (fdEntry_t*)calloc(1 << fdTableEntryArrayBits, sizeof(fdEntry_t)); + if (fdTable[0] == NULL) { + fprintf(stderr, "library initialization failed - " + "unable to allocate file descriptor table - out of memory"); + abort(); + } /* * Setup the signal handler */ sa.sa_handler = sig_wakeup;
*** 109,122 **** * Return the fd table for this fd or NULL is fd out * of range. */ static inline fdEntry_t *getFdEntry(int fd) { ! if (fd < 0 || fd >= fdCount) { return NULL; } ! return &fdTable[fd]; } /* * Start a blocking operation :- * Insert thread onto thread list for the fd. --- 144,191 ---- * Return the fd table for this fd or NULL is fd out * of range. */ static inline fdEntry_t *getFdEntry(int fd) { ! int rootArrayIndex; ! int entryArrayIndex; ! unsigned rootArrayMask; ! unsigned entryArrayMask; ! fdEntry_t* entryTable = NULL; ! ! if (fd < 0) { return NULL; } ! ! entryArrayMask = (1 << fdTableEntryArrayBits) - 1; ! rootArrayMask = ! ((1 << (fdTableRootArrayBits + fdTableEntryArrayBits)) - 1) & ~entryArrayMask; ! ! entryArrayIndex = fd & entryArrayMask; ! rootArrayIndex = (fd & rootArrayMask) >> fdTableEntryArrayBits; ! ! if (rootArrayIndex == 0) { ! /* fast path: first entry array gets preallocated. */ ! entryTable = fdTable[0]; ! } else { ! /* Slow path: check if entry array exists, create it if needed */ ! pthread_mutex_lock(&fdTableLock); ! if (fdTable[rootArrayIndex] == NULL) { ! entryTable = (fdEntry_t*)calloc(1 << fdTableEntryArrayBits, sizeof(fdEntry_t)); ! if (entryTable == NULL) { ! fprintf(stderr, "Unable to allocate file descriptor table - out of memory"); ! pthread_mutex_unlock(&fdTableLock); ! abort(); ! } ! fdTable[rootArrayIndex] = entryTable; ! } else { ! entryTable = fdTable[rootArrayIndex]; ! } ! pthread_mutex_unlock(&fdTableLock); ! } ! ! return entryTable + entryArrayIndex; } /* * Start a blocking operation :- * Insert thread onto thread list for the fd.
< prev index next >