xref: /titanic_50/usr/src/cmd/prstat/prfile.c (revision c77a61a72b5ecdc507d6cf104142edd371a16c84)
1  /*
2   * CDDL HEADER START
3   *
4   * The contents of this file are subject to the terms of the
5   * Common Development and Distribution License, Version 1.0 only
6   * (the "License").  You may not use this file except in compliance
7   * with the License.
8   *
9   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10   * or http://www.opensolaris.org/os/licensing.
11   * See the License for the specific language governing permissions
12   * and limitations under the License.
13   *
14   * When distributing Covered Code, include this CDDL HEADER in each
15   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16   * If applicable, add the following below this CDDL HEADER, with the
17   * fields enclosed by brackets "[]" replaced with your own identifying
18   * information: Portions Copyright [yyyy] [name of copyright owner]
19   *
20   * CDDL HEADER END
21   */
22  /*
23   * Copyright (c) 1999 by Sun Microsystems, Inc.
24   * All rights reserved.
25   */
26  
27  #pragma ident	"%Z%%M%	%I%	%E% SMI"
28  
29  #include <sys/stat.h>
30  #include <fcntl.h>
31  #include <unistd.h>
32  #include <stdlib.h>
33  #include <errno.h>
34  #include <string.h>
35  #include <strings.h>
36  
37  #include "prtable.h"
38  #include "prutil.h"
39  #include "prfile.h"
40  
41  #define	FDS_TABLE_SIZE	1024
42  
43  static fd_t *fd_tbl = NULL;
44  static int fd_max;
45  static int fd_cnt;
46  static int fd_cnt_cur;
47  static int fd_cnt_old;
48  static fds_t *fds_tbl[FDS_TABLE_SIZE];
49  
50  void
51  fd_init(int n)
52  {
53  	fd_max = n;
54  	fd_cnt = fd_cnt_cur = fd_cnt_old = 0;
55  	fd_tbl = Zalloc(sizeof (fd_t) * n);
56  	(void) memset(fds_tbl, 0, sizeof (fds_t *) * FDS_TABLE_SIZE);
57  }
58  
59  void
60  fd_exit()
61  {
62  	if (fd_tbl)
63  		free(fd_tbl);
64  }
65  
66  void
67  fd_close(fd_t *fdp)
68  {
69  	if (fdp) {
70  		if (fdp->fd_fd >= 0 && fdp->fd_name[0] != '\0') {
71  			(void) close(fdp->fd_fd);
72  			fd_cnt--;
73  		}
74  
75  		(void) memset(fdp, 0, sizeof (fd_t));
76  		fdp->fd_fd = -1;
77  	}
78  }
79  
80  void
81  fd_closeall()
82  {
83  	fd_t *fdp = fd_tbl;
84  	int i;
85  
86  	for (i = 0; i < fd_max; i++) {
87  		fd_close(fdp);
88  		fdp++;
89  	}
90  }
91  
92  static void
93  fd_recycle()
94  {
95  	fd_t *fdp = fd_tbl;
96  	int counter;
97  	int i;
98  
99  	counter = abs(fd_cnt_old - fd_cnt) + NUM_RESERVED_FD;
100  
101  	for (i = 0; i < fd_max; i++, fdp++) {
102  
103  		if (fdp->fd_fd == -1)
104  			continue;	/* skip recycled ones */
105  
106  		if (fdp->fd_name[0] != '\0') {	/* file has name */
107  			(void) close(fdp->fd_fd);
108  			fd_cnt--;
109  			counter--;
110  			fdp->fd_fd = -1;
111  		}
112  
113  		if (counter == 0)
114  			break;
115  	}
116  }
117  
118  fd_t *
119  fd_open(char *name, int flags, fd_t *fdp)
120  {
121  	fd_t *fdp_new;
122  	int fd;
123  
124  	if (fd_cnt > fd_max - NUM_RESERVED_FD)
125  		fd_recycle();
126  
127  	if (fdp != NULL) {
128  		if ((strcmp(fdp->fd_name, name) == 0) && (fdp->fd_fd >= 0)) {
129  			fd_cnt_cur++;
130  			return (fdp);
131  		}
132  	}
133  
134  again:	fd = open(name, flags);
135  
136  	if (fd == -1) {
137  		if ((errno == EMFILE) || (errno == ENFILE)) {
138  			fd_recycle();
139  			goto again;
140  		}
141  		fdp_new = NULL;
142  	} else {
143  		fdp_new = &fd_tbl[fd];
144  		fdp_new->fd_fd = fd;
145  		fdp_new->fd_flags = flags;
146  		(void) strcpy(fdp_new->fd_name, name);
147  		fd_cnt++;
148  		fd_cnt_cur++;
149  	}
150  	return (fdp_new);
151  }
152  
153  int
154  fd_getfd(fd_t *fdp)
155  {
156  	return (fdp->fd_fd);
157  }
158  
159  void
160  fd_update()
161  {
162  	fd_cnt_old = fd_cnt_cur;
163  	fd_cnt_cur = 0;
164  }
165  
166  fds_t *
167  fds_get(pid_t pid)
168  {
169  	fds_t *fdsp;
170  	int hash = pid % FDS_TABLE_SIZE;
171  
172  	for (fdsp = fds_tbl[hash]; fdsp; fdsp = fdsp->fds_next)
173  		if (fdsp->fds_pid == pid)	/* searching for pid */
174  			return (fdsp);
175  
176  	fdsp = Zalloc(sizeof (fds_t));	/* adding new if pid was not found */
177  	fdsp->fds_pid = pid;
178  	fdsp->fds_next = fds_tbl[hash];
179  	fds_tbl[hash] = fdsp;
180  	return (fdsp);
181  }
182  
183  void
184  fds_rm(pid_t pid)
185  {
186  	fds_t *fds;
187  	fds_t *fds_prev = NULL;
188  	int hash = pid % FDS_TABLE_SIZE;
189  
190  	for (fds = fds_tbl[hash]; fds && fds->fds_pid != pid;
191  	    fds = fds->fds_next)	/* finding pid */
192  		fds_prev = fds;
193  
194  	if (fds) {			/* if pid was found */
195  
196  		fd_close(fds->fds_psinfo);
197  		fd_close(fds->fds_usage);
198  		fd_close(fds->fds_lpsinfo);
199  		fd_close(fds->fds_lusage);
200  
201  		if (fds_prev)
202  			fds_prev->fds_next = fds->fds_next;
203  		else
204  			fds_tbl[hash] = fds->fds_next;
205  
206  		free(fds);
207  	}
208  }
209