< 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 >