summaryrefslogtreecommitdiff
path: root/usr/src/lib/libaio/common/ma.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libaio/common/ma.c')
-rw-r--r--usr/src/lib/libaio/common/ma.c449
1 files changed, 0 insertions, 449 deletions
diff --git a/usr/src/lib/libaio/common/ma.c b/usr/src/lib/libaio/common/ma.c
deleted file mode 100644
index e5b26be616..0000000000
--- a/usr/src/lib/libaio/common/ma.c
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include "libaio.h"
-
-/*
- * libaio memory allocation strategy:
- *
- * For each of the structure types we wish to allocate/free
- * (aio_worker_t, aio_req_t, aio_lio_t), we use mmap() to allocate
- * chunks of memory which are then subdivided into individual
- * elements which are put into a free list from which allocations
- * are made and to which frees are returned.
- *
- * Chunks start small (8 Kbytes) and get larger (size doubling)
- * as more chunks are needed. This keeps memory usage small for
- * light use and fragmentation small for heavy use.
- *
- * Chunks are never unmapped except as an aftermath of fork()
- * in the child process, when they are all unmapped (because
- * all of the worker threads disappear in the child).
- */
-
-#define INITIAL_CHUNKSIZE (8 * 1024)
-
-/*
- * The header structure for each chunk.
- * A pointer and a size_t ensures proper alignment for whatever follows.
- */
-typedef struct chunk {
- struct chunk *chunk_next; /* linked list */
- size_t chunk_size; /* size of this chunk */
-} chunk_t;
-
-chunk_t *chunk_list = NULL; /* list of all chunks */
-mutex_t chunk_lock = DEFAULTMUTEX;
-
-chunk_t *
-chunk_alloc(size_t size)
-{
- chunk_t *chp = NULL;
- void *ptr;
-
- ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANON, -1, (off_t)0);
- if (ptr != MAP_FAILED) {
- sig_mutex_lock(&chunk_lock);
- chp = ptr;
- chp->chunk_next = chunk_list;
- chunk_list = chp;
- chp->chunk_size = size;
- sig_mutex_unlock(&chunk_lock);
- }
-
- return (chp);
-}
-
-aio_worker_t *worker_freelist = NULL; /* free list of worker structures */
-aio_worker_t *worker_freelast = NULL;
-size_t worker_chunksize = 0;
-mutex_t worker_lock = DEFAULTMUTEX;
-
-/*
- * Allocate a worker control block.
- */
-aio_worker_t *
-_aio_worker_alloc(void)
-{
- aio_worker_t *aiowp;
- chunk_t *chp;
- size_t chunksize;
- int nelem;
- int i;
-
- sig_mutex_lock(&worker_lock);
- if ((aiowp = worker_freelist) == NULL) {
- if ((chunksize = 2 * worker_chunksize) == 0)
- chunksize = INITIAL_CHUNKSIZE;
- if ((chp = chunk_alloc(chunksize)) == NULL) {
- sig_mutex_unlock(&worker_lock);
- return (NULL);
- }
- worker_chunksize = chunksize;
- worker_freelist = (aio_worker_t *)(uintptr_t)(chp + 1);
- nelem = (chunksize - sizeof (chunk_t)) / sizeof (aio_worker_t);
- for (i = 0, aiowp = worker_freelist; i < nelem; i++, aiowp++)
- aiowp->work_forw = aiowp + 1;
- worker_freelast = aiowp - 1;
- worker_freelast->work_forw = NULL;
- aiowp = worker_freelist;
- }
- if ((worker_freelist = aiowp->work_forw) == NULL)
- worker_freelast = NULL;
- sig_mutex_unlock(&worker_lock);
-
- aiowp->work_forw = NULL;
- (void) mutex_init(&aiowp->work_qlock1, USYNC_THREAD, NULL);
- (void) cond_init(&aiowp->work_idle_cv, USYNC_THREAD, NULL);
-
- return (aiowp);
-}
-
-/*
- * Free a worker control block.
- * Declared with void *arg so it can be a pthread_key_create() destructor.
- */
-void
-_aio_worker_free(void *arg)
-{
- aio_worker_t *aiowp = arg;
-
- (void) mutex_destroy(&aiowp->work_qlock1);
- (void) cond_destroy(&aiowp->work_idle_cv);
- (void) memset(aiowp, 0, sizeof (*aiowp));
-
- sig_mutex_lock(&worker_lock);
- if (worker_freelast == NULL) {
- worker_freelist = worker_freelast = aiowp;
- } else {
- worker_freelast->work_forw = aiowp;
- worker_freelast = aiowp;
- }
- sig_mutex_unlock(&worker_lock);
-}
-
-aio_req_t *_aio_freelist = NULL; /* free list of request structures */
-aio_req_t *_aio_freelast = NULL;
-size_t request_chunksize = 0;
-int _aio_freelist_cnt = 0;
-int _aio_allocated_cnt = 0;
-mutex_t __aio_cache_lock = DEFAULTMUTEX;
-
-/*
- * Allocate an aio request structure.
- */
-aio_req_t *
-_aio_req_alloc(void)
-{
- aio_req_t *reqp;
- chunk_t *chp;
- size_t chunksize;
- int nelem;
- int i;
-
- sig_mutex_lock(&__aio_cache_lock);
- if ((reqp = _aio_freelist) == NULL) {
- if ((chunksize = 2 * request_chunksize) == 0)
- chunksize = INITIAL_CHUNKSIZE;
- if ((chp = chunk_alloc(chunksize)) == NULL) {
- sig_mutex_unlock(&__aio_cache_lock);
- return (NULL);
- }
- request_chunksize = chunksize;
- _aio_freelist = (aio_req_t *)(uintptr_t)(chp + 1);
- nelem = (chunksize - sizeof (chunk_t)) / sizeof (aio_req_t);
- for (i = 0, reqp = _aio_freelist; i < nelem; i++, reqp++) {
- reqp->req_state = AIO_REQ_FREE;
- reqp->req_link = reqp + 1;
- }
- _aio_freelast = reqp - 1;
- _aio_freelast->req_link = NULL;
- _aio_freelist_cnt = nelem;
- reqp = _aio_freelist;
- }
- if ((_aio_freelist = reqp->req_link) == NULL)
- _aio_freelast = NULL;
- _aio_freelist_cnt--;
- _aio_allocated_cnt++;
- sig_mutex_unlock(&__aio_cache_lock);
-
- ASSERT(reqp->req_state == AIO_REQ_FREE);
- reqp->req_state = 0;
- reqp->req_link = NULL;
- reqp->req_sigevent.sigev_notify = SIGEV_NONE;
-
- return (reqp);
-}
-
-/*
- * Free an aio request structure.
- */
-void
-_aio_req_free(aio_req_t *reqp)
-{
- ASSERT(reqp->req_state != AIO_REQ_FREE &&
- reqp->req_state != AIO_REQ_DONEQ);
- (void) memset(reqp, 0, sizeof (*reqp));
- reqp->req_state = AIO_REQ_FREE;
-
- sig_mutex_lock(&__aio_cache_lock);
- if (_aio_freelast == NULL) {
- _aio_freelist = _aio_freelast = reqp;
- } else {
- _aio_freelast->req_link = reqp;
- _aio_freelast = reqp;
- }
- _aio_freelist_cnt++;
- _aio_allocated_cnt--;
- sig_mutex_unlock(&__aio_cache_lock);
-}
-
-aio_lio_t *_lio_head_freelist = NULL; /* free list of lio head structures */
-aio_lio_t *_lio_head_freelast = NULL;
-size_t lio_head_chunksize = 0;
-int _lio_alloc = 0;
-int _lio_free = 0;
-mutex_t __lio_mutex = DEFAULTMUTEX;
-
-/*
- * Allocate a listio head structure.
- */
-aio_lio_t *
-_aio_lio_alloc(void)
-{
- aio_lio_t *head;
- chunk_t *chp;
- size_t chunksize;
- int nelem;
- int i;
-
- sig_mutex_lock(&__lio_mutex);
- if ((head = _lio_head_freelist) == NULL) {
- if ((chunksize = 2 * lio_head_chunksize) == 0)
- chunksize = INITIAL_CHUNKSIZE;
- if ((chp = chunk_alloc(chunksize)) == NULL) {
- sig_mutex_unlock(&__lio_mutex);
- return (NULL);
- }
- lio_head_chunksize = chunksize;
- _lio_head_freelist = (aio_lio_t *)(uintptr_t)(chp + 1);
- nelem = (chunksize - sizeof (chunk_t)) / sizeof (aio_lio_t);
- for (i = 0, head = _lio_head_freelist; i < nelem; i++, head++)
- head->lio_next = head + 1;
- _lio_head_freelast = head - 1;
- _lio_head_freelast->lio_next = NULL;
- _lio_alloc += nelem;
- _lio_free = nelem;
- head = _lio_head_freelist;
- }
- if ((_lio_head_freelist = head->lio_next) == NULL)
- _lio_head_freelast = NULL;
- _lio_free--;
- sig_mutex_unlock(&__lio_mutex);
-
- ASSERT(head->lio_nent == 0 && head->lio_refcnt == 0);
- head->lio_next = NULL;
- head->lio_port = -1;
- (void) mutex_init(&head->lio_mutex, USYNC_THREAD, NULL);
- (void) cond_init(&head->lio_cond_cv, USYNC_THREAD, NULL);
-
- return (head);
-}
-
-/*
- * Free a listio head structure.
- */
-void
-_aio_lio_free(aio_lio_t *head)
-{
- ASSERT(head->lio_nent == 0 && head->lio_refcnt == 0);
- (void) mutex_destroy(&head->lio_mutex);
- (void) cond_destroy(&head->lio_cond_cv);
- (void) memset(head, 0, sizeof (*head));
-
- sig_mutex_lock(&__lio_mutex);
- if (_lio_head_freelast == NULL) {
- _lio_head_freelist = _lio_head_freelast = head;
- } else {
- _lio_head_freelast->lio_next = head;
- _lio_head_freelast = head;
- }
- _lio_free++;
- sig_mutex_unlock(&__lio_mutex);
-}
-
-static void
-_aio_prepare_fork(void)
-{
- /* acquire locks */
- sig_mutex_lock(&chunk_lock);
-}
-
-static void
-_aio_parent_fork(void)
-{
- /* release locks */
- sig_mutex_unlock(&chunk_lock);
-}
-
-static void
-_aio_child_fork(void)
-{
- chunk_t *chp;
-
- _aio_parent_fork(); /* release locks */
-
- /*
- * All of the workers are gone; free their structures.
- */
- if (_kaio_supported != NULL) {
- (void) munmap((void *)_kaio_supported,
- MAX_KAIO_FDARRAY_SIZE * sizeof (uint32_t));
- _kaio_supported = NULL;
- }
- if (_aio_hash != NULL) {
- (void) munmap((void *)_aio_hash, HASHSZ * sizeof (aio_hash_t));
- _aio_hash = NULL;
- }
- for (chp = chunk_list; chp != NULL; chp = chunk_list) {
- chunk_list = chp->chunk_next;
- (void) munmap((void *)chp, chp->chunk_size);
- }
-
- /*
- * Reinitialize global variables
- */
-
- worker_freelist = NULL;
- worker_freelast = NULL;
- worker_chunksize = 0;
- (void) mutex_init(&worker_lock, USYNC_THREAD, NULL);
-
- _aio_freelist = NULL;
- _aio_freelast = NULL;
- request_chunksize = 0;
- _aio_freelist_cnt = 0;
- _aio_allocated_cnt = 0;
- (void) mutex_init(&__aio_cache_lock, USYNC_THREAD, NULL);
-
- _lio_head_freelist = NULL;
- _lio_head_freelast = NULL;
- lio_head_chunksize = 0;
- _lio_alloc = 0;
- _lio_free = 0;
- (void) mutex_init(&__lio_mutex, USYNC_THREAD, NULL);
-
- (void) mutex_init(&__aio_initlock, USYNC_THREAD, NULL);
- (void) mutex_init(&__aio_mutex, USYNC_THREAD, NULL);
- (void) cond_init(&_aio_iowait_cv, USYNC_THREAD, NULL);
- (void) cond_init(&_aio_waitn_cv, USYNC_THREAD, NULL);
-
- _kaio_ok = 0;
- __uaio_ok = 0;
-
- _kaiowp = NULL;
-
- __workers_rw = NULL;
- __nextworker_rw = NULL;
- __rw_workerscnt = 0;
-
- __workers_no = NULL;
- __nextworker_no = NULL;
- __no_workerscnt = 0;
-
- _aio_worker_cnt = 0;
-
- _aio_done_head = NULL;
- _aio_done_tail = NULL;
- _aio_donecnt = 0;
-
- _aio_doneq = NULL;
- _aio_doneq_cnt = 0;
-
- _aio_waitncnt = 0;
- _aio_outstand_cnt = 0;
- _kaio_outstand_cnt = 0;
- _aio_req_done_cnt = 0;
- _aio_kernel_suspend = 0;
- _aio_suscv_cnt = 0;
-
- _aiowait_flag = 0;
- _aio_flags = 0;
-}
-
-#define DISPLAY(var) \
- (void) fprintf(stderr, #var "\t= %d\n", var)
-
-static void
-_aio_exit_info(void)
-{
- if ((_kaio_ok | __uaio_ok) == 0)
- return;
- (void) fprintf(stderr, "\n");
- DISPLAY(_aio_freelist_cnt);
- DISPLAY(_aio_allocated_cnt);
- DISPLAY(_lio_alloc);
- DISPLAY(_lio_free);
- DISPLAY(__rw_workerscnt);
- DISPLAY(__no_workerscnt);
- DISPLAY(_aio_worker_cnt);
- DISPLAY(_aio_donecnt);
- DISPLAY(_aio_doneq_cnt);
- DISPLAY(_aio_waitncnt);
- DISPLAY(_aio_outstand_cnt);
- DISPLAY(_kaio_outstand_cnt);
- DISPLAY(_aio_req_done_cnt);
- DISPLAY(_aio_kernel_suspend);
- DISPLAY(_aio_suscv_cnt);
- DISPLAY(_aiowait_flag);
- DISPLAY(_aio_flags);
-}
-
-#pragma init(_aio_init)
-static void
-_aio_init(void)
-{
- char *str;
-
- (void) pthread_key_create(&_aio_key, _aio_worker_free);
- (void) pthread_atfork(_aio_prepare_fork,
- _aio_parent_fork, _aio_child_fork);
- if ((str = getenv("_AIO_MIN_WORKERS")) != NULL) {
- if ((_min_workers = atoi(str)) <= 0)
- _min_workers = 8;
- }
- if ((str = getenv("_AIO_MAX_WORKERS")) != NULL) {
- if ((_max_workers = atoi(str)) <= 0)
- _max_workers = 256;
- if (_max_workers < _min_workers + 1)
- _max_workers = _min_workers + 1;
- }
- if ((str = getenv("_AIO_EXIT_INFO")) != NULL && atoi(str) != 0)
- (void) atexit(_aio_exit_info);
-}