fdpool.c revision f79b2dff1024db4f6326f3422236bed169dd902f
1f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle/* 2f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * Copyright (C) 2010 The Android Open Source Project 3f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * 4f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * Licensed under the Apache License, Version 2.0 (the "License"); 5f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * you may not use this file except in compliance with the License. 6f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * You may obtain a copy of the License at 7f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * 8f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * http://www.apache.org/licenses/LICENSE-2.0 9f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * 10f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * Unless required by applicable law or agreed to in writing, software 11f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * distributed under the License is distributed on an "AS IS" BASIS, 12f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * See the License for the specific language governing permissions and 14f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle * limitations under the License. 15f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle */ 16f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 17f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include <assert.h> 18f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include <errno.h> 19f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include <fcntl.h> 20f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include <unistd.h> 21f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include <utils.h> 22f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 23f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#include "fdpool.h" 24f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 25f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#define INVALID_FD (-1) 26f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle#define FDPOOL_SIZE 4 27f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 28f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlestatic struct pooled_fd fdpool_head = { 29f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle .fd = INVALID_FD, 30f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle .prev = &fdpool_head, 31f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle .next = &fdpool_head 32f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle}; 33f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlestatic int fdpool_count = 0; 34f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 35f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlestatic void fdpool_insert_head(struct pooled_fd *node) { 36f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle struct pooled_fd *prev = &fdpool_head; 37f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle struct pooled_fd *next = prev->next; 38f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 39f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle assert(node); 40f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 41f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle prev->next = node; 42f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle node->prev = prev; 43f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle node->next = next; 44f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle next->prev = node; 45f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 46f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle fdpool_count++; 47f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle} 48f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 49f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlestatic void fdpool_remove(struct pooled_fd *node) { 50f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle struct pooled_fd *prev = node->prev; 51f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle struct pooled_fd *next = node->next; 52f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 53f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle assert(prev); 54f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle assert(next); 55f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 56f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle prev->next = next; 57f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle next->prev = prev; 58f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 59f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle fdpool_count--; 60f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle} 61f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 62f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlestatic struct pooled_fd *fdpool_remove_tail(void) { 63f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle struct pooled_fd *tail = fdpool_head.prev; 64f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 65f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle assert(tail != &fdpool_head); 66f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 67f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle fdpool_remove(tail); 68f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 69f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle return tail; 70f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle} 71f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 72f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlestatic void fdpool_clear(struct pooled_fd *pfd) { 73f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle assert(pfd); 74f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 75f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle pfd->fd = INVALID_FD; 76f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle pfd->prev = pfd->next = NULL; 77f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle} 78f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 79f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlestatic void fdpool_unpool(struct pooled_fd *pfd) { 80f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle close(pfd->fd); 81f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle fdpool_clear(pfd); 82f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle} 83f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 84f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlestatic void fdpool_evict(void) { 85f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle struct pooled_fd *tail; 86f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 87f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle tail = fdpool_remove_tail(); 88f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle fdpool_unpool(tail); 89f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle} 90f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 91f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlestatic void fdpool_pool(struct pooled_fd *pfd, int fd) { 92f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle if (fdpool_count >= FDPOOL_SIZE) 93f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle fdpool_evict(); 94f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 95f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle fdpool_insert_head(pfd); 96f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle pfd->fd = fd; 97f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle} 98f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 99f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlestatic void fdpool_touch(struct pooled_fd *pfd) { 100f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle fdpool_remove(pfd); 101f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle fdpool_insert_head(pfd); 102f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle} 103f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 104f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 105f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 106f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlevoid fdpool_init(struct pooled_fd *pfd) { 107f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle fdpool_clear(pfd); 108f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle} 109f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 110f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttleint fdpool_open(struct pooled_fd *pfd, const char *pathname, int flags) { 111f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle int open_errno; 112f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle int fd; 113f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 114f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle if (pfd->fd != INVALID_FD) { 115f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle fdpool_touch(pfd); 116f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle return pfd->fd; 117f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle } 118f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 119f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle fd = open(pathname, flags); 120f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle open_errno = errno; 121f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 122f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle if (fd >= 0) { 123f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle fdpool_pool(pfd, fd); 124f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle } 125f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 126f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle errno = open_errno; 127f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle return fd; 128f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle} 129f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 130f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttlevoid fdpool_close(struct pooled_fd *pfd) { 131f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle assert(pfd); 132f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle 133f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle fdpool_unpool(pfd); 134f79b2dff1024db4f6326f3422236bed169dd902fThomas Tuttle} 135