Home | History | Annotate | Download | only in prstat
      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