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