< prev index next >
src/java.base/aix/native/libnet/aix_close.c
Print this page
rev 13795 : 8150460: (linux|bsd|aix)_close.c: file descriptor table may become large or may not work at all
Reviewed-by:
*** 1,7 ****
/*
! * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
--- 1,8 ----
/*
! * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
! * Copyright (c) 2016, SAP SE and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
*** 48,57 ****
--- 49,60 ----
and another thread is calling select with the same file descriptor, the
close subroutine does not return until the select call returns.
...
*/
+ #include <assert.h>
+ #include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <pthread.h>
#include <sys/types.h>
*** 84,97 ****
* Signal to unblock thread
*/
static int sigWakeup = (SIGRTMAX - 1);
/*
! * The fd table and the number of file descriptors
! */
! static fdEntry_t *fdTable = NULL;
! static int fdCount = 0;
/*
* Null signal handler
*/
static void sig_wakeup(int sig) {
--- 87,122 ----
* Signal to unblock thread
*/
static int sigWakeup = (SIGRTMAX - 1);
/*
! * fdTable holds one entry per file descriptor, up to a certain
! * maximum.
! * Theoretically, the number of possible file descriptors can get
! * large, though usually it does not. To save memory, we keep file
! * descriptors with large numerical values in an overflow table. That
! * table is organized as a two-dimensional sparse array, allocated
! * on demand.
! */
!
! static fdEntry_t* fdTable;
! /* Max. number of file descriptors in fdTable. */
! static const int fdTableMaxSize = 0x1000; /* 4K */
! /* Max. theoretical number of file descriptor on system. */
! static int fdLimit;
! /* Length of fdTable, in number of entries. */
! static int fdTableLen;
!
! /* Overflow table: organized as array of n slabs, each holding
! * 64k entries.
! */
! static fdEntry_t** fdOverflowTable;
! /* Number of slabs in the overflow table */
! static int fdOverflowTableLen;
! /* Number of entries in one slab */
! static const int fdOverflowTableSlabSize = 0x10000; /* 64k */
! pthread_mutex_t fdOverflowTableLock = PTHREAD_MUTEX_INITIALIZER;
/*
* Null signal handler
*/
static void sig_wakeup(int sig) {
*** 106,151 ****
*/
void aix_close_init() {
struct rlimit nbr_files;
sigset_t sigset;
struct sigaction sa;
! /* Check already initialized */
! if (fdCount > 0 && fdTable != NULL) {
! return;
! }
! /*
! * Allocate table based on the maximum number of
! * file descriptors.
! */
! if (-1 == getrlimit(RLIMIT_NOFILE, &nbr_files)) {
! fprintf(stderr, "library initialization failed - "
! "unable to get max # of allocated fds\n");
! abort();
! }
! fdCount = nbr_files.rlim_max;
! /*
! * We have a conceptual problem here, when the number of files is
! * unlimited. As a kind of workaround, we ensure the table is big
! * enough for handle even a large number of files. Since SAP itself
! * recommends a limit of 32000 files, we just use 64000 as 'infinity'.
! */
! if (nbr_files.rlim_max == RLIM_INFINITY) {
! fdCount = 64000;
! }
! 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();
}
! {
! int i;
! for (i=0; i < fdCount; i++) {
! pthread_mutex_init(&fdTable[i].lock, NULL);
}
}
/*
* Setup the signal handler
--- 131,174 ----
*/
void aix_close_init() {
struct rlimit nbr_files;
sigset_t sigset;
struct sigaction sa;
+ int i = 0;
! assert(fdTable == NULL);
! /* Determine the maximum number of possible file descriptors. */
! getrlimit(RLIMIT_NOFILE, &nbr_files);
! if (nbr_files.rlim_max != RLIM_INFINITY) {
! fdLimit = nbr_files.rlim_max;
! } else {
! /* We just do not know. */
! fdLimit = INT_MAX;
! }
!
! /* Allocate table for low value file descriptors. */
! fdTableLen = fdLimit < fdTableMaxSize ? fdLimit : fdTableMaxSize;
! fdTable = (fdEntry_t*) calloc(fdTableLen, sizeof(fdEntry_t));
if (fdTable == NULL) {
fprintf(stderr, "library initialization failed - "
"unable to allocate file descriptor table - out of memory");
abort();
+ } else {
+ for (i = 0; i < fdTableLen; i ++) {
+ pthread_mutex_init(&fdTable[i].lock, NULL);
+ }
}
! /* Allocate overflow table, if needed */
! if (fdLimit > fdTableMaxSize) {
! fdOverflowTableLen = ((fdLimit - fdTableMaxSize) / fdOverflowTableSlabSize) + 1;
! fdOverflowTable = (fdEntry_t**) calloc(fdOverflowTableLen, sizeof(fdEntry_t*));
! if (fdOverflowTable == NULL) {
! fprintf(stderr, "library initialization failed - "
! "unable to allocate file descriptor overflow table - out of memory");
! abort();
}
}
/*
* Setup the signal handler
*** 159,177 ****
sigaddset(&sigset, sigWakeup);
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
}
/*
! * 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.
--- 182,234 ----
sigaddset(&sigset, sigWakeup);
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
}
/*
! * Return the fd table for this fd.
*/
static inline fdEntry_t *getFdEntry(int fd)
{
! fdEntry_t* result = NULL;
!
! if (fd < 0) {
return NULL;
}
!
! /* This should not happen. If it does, our assumption about
! * max. fd value was wrong. */
! assert(fd < fdLimit);
!
! if (fd < fdTableMaxSize) {
! assert(fd < fdTableLen);
! result = fdTable + fd;
! } else {
! const int indexInOverflowTable = fd - fdTableMaxSize;
! const int rootindex = indexInOverflowTable / fdOverflowTableSlabSize;
! const int slabindex = indexInOverflowTable % fdOverflowTableSlabSize;
! assert(rootindex < fdOverflowTableLen);
! assert(slabindex < fdOverflowTableSlabSize);
! pthread_mutex_lock(&fdOverflowTableLock);
! if (fdOverflowTable[rootindex] == NULL) {
! fdEntry_t* const newSlab =
! (fdEntry_t*)calloc(fdOverflowTableSlabSize, sizeof(fdEntry_t));
! if (newSlab == NULL) {
! fprintf(stderr, "Unable to allocate file descriptor table - out of memory");
! pthread_mutex_unlock(&fdOverflowTableLock);
! abort();
! } else {
! int i;
! for (i = 0; i < fdOverflowTableSlabSize; i ++) {
! pthread_mutex_init(&newSlab[i].lock, NULL);
! }
! fdOverflowTable[rootindex] = newSlab;
! }
! }
! pthread_mutex_unlock(&fdOverflowTableLock);
! result = fdOverflowTable[rootindex] + slabindex;
! }
! return result;
}
/*
* Start a blocking operation :-
* Insert thread onto thread list for the fd.
< prev index next >