Move compat to common and create an internal lib
[lttng-tools.git] / src / common / compat / compat-poll.c
1 /*
2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; only version 2 of the License.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15 * Place - Suite 330, Boston, MA 02111-1307, USA.
16 */
17
18 #include <stdlib.h>
19 #include <sys/resource.h>
20 #include <sys/time.h>
21
22 #include <lttngerr.h>
23
24 #include "poll.h"
25
26 unsigned int poll_max_size;
27
28 /*
29 * Create pollfd data structure.
30 */
31 int compat_poll_create(struct lttng_poll_event *events, int size)
32 {
33 if (events == NULL || size <= 0) {
34 ERR("Wrong arguments for poll create");
35 goto error;
36 }
37
38 /* Don't bust the limit here */
39 if (size > poll_max_size) {
40 size = poll_max_size;
41 }
42
43 /* This *must* be freed by using lttng_poll_free() */
44 events->events = zmalloc(size * sizeof(struct pollfd));
45 if (events->events == NULL) {
46 perror("zmalloc struct pollfd");
47 goto error;
48 }
49
50 events->events_size = size;
51 events->nb_fd = 0;
52
53 return 0;
54
55 error:
56 return -1;
57 }
58
59 /*
60 * Add fd to pollfd data structure with requested events.
61 */
62 int compat_poll_add(struct lttng_poll_event *events, int fd,
63 uint32_t req_events)
64 {
65 int new_size;
66 struct pollfd *ptr;
67
68 if (events == NULL || events->events == NULL || fd < 0) {
69 ERR("Bad compat poll add arguments");
70 goto error;
71 }
72
73 /* Reallocate pollfd structure by a factor of 2 if needed. */
74 if (events->nb_fd >= events->events_size) {
75 new_size = 2 * events->events_size;
76 ptr = realloc(events->events, new_size * sizeof(struct pollfd));
77 if (ptr == NULL) {
78 perror("realloc poll add");
79 goto error;
80 }
81 events->events = ptr;
82 events->events_size = new_size;
83 }
84
85 events->events[events->nb_fd].fd = fd;
86 events->events[events->nb_fd].events = req_events;
87 events->nb_fd++;
88
89 DBG("fd %d of %d added to pollfd", fd, events->nb_fd);
90
91 return 0;
92
93 error:
94 return -1;
95 }
96
97 /*
98 * Remove a fd from the pollfd structure.
99 */
100 int compat_poll_del(struct lttng_poll_event *events, int fd)
101 {
102 int new_size, i, count = 0;
103 struct pollfd *old = NULL, *new = NULL;
104
105 if (events == NULL || events->events == NULL || fd < 0) {
106 ERR("Wrong arguments for poll del");
107 goto error;
108 }
109
110 old = events->events;
111 new_size = events->events_size - 1;
112
113 /* Safety check on size */
114 if (new_size > poll_max_size) {
115 new_size = poll_max_size;
116 }
117
118 new = zmalloc(new_size * sizeof(struct pollfd));
119 if (new == NULL) {
120 perror("zmalloc poll del");
121 goto error;
122 }
123
124 for (i = 0; i < events->events_size; i++) {
125 /* Don't put back the fd we want to delete */
126 if (old[i].fd != fd) {
127 new[count].fd = old[i].fd;
128 new[count].events = old[i].events;
129 count++;
130 }
131 }
132
133 events->events_size = new_size;
134 events->events = new;
135 events->nb_fd--;
136
137 free(old);
138
139 return 0;
140
141 error:
142 return -1;
143 }
144
145 /*
146 * Wait on poll() with timeout. Blocking call.
147 */
148 int compat_poll_wait(struct lttng_poll_event *events, int timeout)
149 {
150 int ret;
151
152 if (events == NULL || events->events == NULL ||
153 events->events_size < events->nb_fd) {
154 ERR("poll wait arguments error");
155 goto error;
156 }
157
158 ret = poll(events->events, events->nb_fd, timeout);
159 if (ret < 0) {
160 /* At this point, every error is fatal */
161 perror("poll wait");
162 goto error;
163 }
164
165 return ret;
166
167 error:
168 return -1;
169 }
170
171 /*
172 * Setup poll set maximum size.
173 */
174 void compat_poll_set_max_size(void)
175 {
176 int ret;
177 struct rlimit lim;
178
179 /* Default value */
180 poll_max_size = LTTNG_POLL_DEFAULT_SIZE;
181
182 ret = getrlimit(RLIMIT_NOFILE, &lim);
183 if (ret < 0) {
184 perror("getrlimit poll RLIMIT_NOFILE");
185 return;
186 }
187
188 poll_max_size = lim.rlim_cur;
189 if (poll_max_size <= 0) {
190 /* Extra precaution */
191 poll_max_size = LTTNG_POLL_DEFAULT_SIZE;
192 }
193
194 DBG("poll set max size set to %u", poll_max_size);
195 }
This page took 0.033763 seconds and 5 git commands to generate.