191007045SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 21b85337dSArnaldo Carvalho de Melo /* 31b85337dSArnaldo Carvalho de Melo * Copyright (C) 2014, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> 41b85337dSArnaldo Carvalho de Melo */ 51b85337dSArnaldo Carvalho de Melo #include "array.h" 61b85337dSArnaldo Carvalho de Melo #include <errno.h> 71b85337dSArnaldo Carvalho de Melo #include <fcntl.h> 81b85337dSArnaldo Carvalho de Melo #include <poll.h> 91b85337dSArnaldo Carvalho de Melo #include <stdlib.h> 101b85337dSArnaldo Carvalho de Melo #include <unistd.h> 11ab4c1f9fSAlexey Budankov #include <string.h> 121b85337dSArnaldo Carvalho de Melo 131b85337dSArnaldo Carvalho de Melo void fdarray__init(struct fdarray *fda, int nr_autogrow) 141b85337dSArnaldo Carvalho de Melo { 151b85337dSArnaldo Carvalho de Melo fda->entries = NULL; 162171a925SArnaldo Carvalho de Melo fda->priv = NULL; 171b85337dSArnaldo Carvalho de Melo fda->nr = fda->nr_alloc = 0; 181b85337dSArnaldo Carvalho de Melo fda->nr_autogrow = nr_autogrow; 191b85337dSArnaldo Carvalho de Melo } 201b85337dSArnaldo Carvalho de Melo 211b85337dSArnaldo Carvalho de Melo int fdarray__grow(struct fdarray *fda, int nr) 221b85337dSArnaldo Carvalho de Melo { 23ab4c1f9fSAlexey Budankov struct priv *priv; 241b85337dSArnaldo Carvalho de Melo int nr_alloc = fda->nr_alloc + nr; 252171a925SArnaldo Carvalho de Melo size_t psize = sizeof(fda->priv[0]) * nr_alloc; 261b85337dSArnaldo Carvalho de Melo size_t size = sizeof(struct pollfd) * nr_alloc; 271b85337dSArnaldo Carvalho de Melo struct pollfd *entries = realloc(fda->entries, size); 281b85337dSArnaldo Carvalho de Melo 291b85337dSArnaldo Carvalho de Melo if (entries == NULL) 301b85337dSArnaldo Carvalho de Melo return -ENOMEM; 311b85337dSArnaldo Carvalho de Melo 322171a925SArnaldo Carvalho de Melo priv = realloc(fda->priv, psize); 332171a925SArnaldo Carvalho de Melo if (priv == NULL) { 342171a925SArnaldo Carvalho de Melo free(entries); 352171a925SArnaldo Carvalho de Melo return -ENOMEM; 362171a925SArnaldo Carvalho de Melo } 372171a925SArnaldo Carvalho de Melo 38ab4c1f9fSAlexey Budankov memset(&entries[fda->nr_alloc], 0, sizeof(struct pollfd) * nr); 39ab4c1f9fSAlexey Budankov memset(&priv[fda->nr_alloc], 0, sizeof(fda->priv[0]) * nr); 40ab4c1f9fSAlexey Budankov 411b85337dSArnaldo Carvalho de Melo fda->nr_alloc = nr_alloc; 421b85337dSArnaldo Carvalho de Melo fda->entries = entries; 432171a925SArnaldo Carvalho de Melo fda->priv = priv; 441b85337dSArnaldo Carvalho de Melo return 0; 451b85337dSArnaldo Carvalho de Melo } 461b85337dSArnaldo Carvalho de Melo 471b85337dSArnaldo Carvalho de Melo struct fdarray *fdarray__new(int nr_alloc, int nr_autogrow) 481b85337dSArnaldo Carvalho de Melo { 491b85337dSArnaldo Carvalho de Melo struct fdarray *fda = calloc(1, sizeof(*fda)); 501b85337dSArnaldo Carvalho de Melo 511b85337dSArnaldo Carvalho de Melo if (fda != NULL) { 521b85337dSArnaldo Carvalho de Melo if (fdarray__grow(fda, nr_alloc)) { 531b85337dSArnaldo Carvalho de Melo free(fda); 541b85337dSArnaldo Carvalho de Melo fda = NULL; 551b85337dSArnaldo Carvalho de Melo } else { 561b85337dSArnaldo Carvalho de Melo fda->nr_autogrow = nr_autogrow; 571b85337dSArnaldo Carvalho de Melo } 581b85337dSArnaldo Carvalho de Melo } 591b85337dSArnaldo Carvalho de Melo 601b85337dSArnaldo Carvalho de Melo return fda; 611b85337dSArnaldo Carvalho de Melo } 621b85337dSArnaldo Carvalho de Melo 631b85337dSArnaldo Carvalho de Melo void fdarray__exit(struct fdarray *fda) 641b85337dSArnaldo Carvalho de Melo { 651b85337dSArnaldo Carvalho de Melo free(fda->entries); 662171a925SArnaldo Carvalho de Melo free(fda->priv); 671b85337dSArnaldo Carvalho de Melo fdarray__init(fda, 0); 681b85337dSArnaldo Carvalho de Melo } 691b85337dSArnaldo Carvalho de Melo 701b85337dSArnaldo Carvalho de Melo void fdarray__delete(struct fdarray *fda) 711b85337dSArnaldo Carvalho de Melo { 721b85337dSArnaldo Carvalho de Melo fdarray__exit(fda); 731b85337dSArnaldo Carvalho de Melo free(fda); 741b85337dSArnaldo Carvalho de Melo } 751b85337dSArnaldo Carvalho de Melo 76ab4c1f9fSAlexey Budankov int fdarray__add(struct fdarray *fda, int fd, short revents, enum fdarray_flags flags) 771b85337dSArnaldo Carvalho de Melo { 782171a925SArnaldo Carvalho de Melo int pos = fda->nr; 792171a925SArnaldo Carvalho de Melo 801b85337dSArnaldo Carvalho de Melo if (fda->nr == fda->nr_alloc && 811b85337dSArnaldo Carvalho de Melo fdarray__grow(fda, fda->nr_autogrow) < 0) 821b85337dSArnaldo Carvalho de Melo return -ENOMEM; 831b85337dSArnaldo Carvalho de Melo 841b85337dSArnaldo Carvalho de Melo fda->entries[fda->nr].fd = fd; 851b85337dSArnaldo Carvalho de Melo fda->entries[fda->nr].events = revents; 86ab4c1f9fSAlexey Budankov fda->priv[fda->nr].flags = flags; 871b85337dSArnaldo Carvalho de Melo fda->nr++; 882171a925SArnaldo Carvalho de Melo return pos; 891b85337dSArnaldo Carvalho de Melo } 901b85337dSArnaldo Carvalho de Melo 91*d87c25e8SAlexey Bayduraev int fdarray__dup_entry_from(struct fdarray *fda, int pos, struct fdarray *from) 92*d87c25e8SAlexey Bayduraev { 93*d87c25e8SAlexey Bayduraev struct pollfd *entry; 94*d87c25e8SAlexey Bayduraev int npos; 95*d87c25e8SAlexey Bayduraev 96*d87c25e8SAlexey Bayduraev if (pos >= from->nr) 97*d87c25e8SAlexey Bayduraev return -EINVAL; 98*d87c25e8SAlexey Bayduraev 99*d87c25e8SAlexey Bayduraev entry = &from->entries[pos]; 100*d87c25e8SAlexey Bayduraev 101*d87c25e8SAlexey Bayduraev npos = fdarray__add(fda, entry->fd, entry->events, from->priv[pos].flags); 102*d87c25e8SAlexey Bayduraev if (npos >= 0) 103*d87c25e8SAlexey Bayduraev fda->priv[npos] = from->priv[pos]; 104*d87c25e8SAlexey Bayduraev 105*d87c25e8SAlexey Bayduraev return npos; 106*d87c25e8SAlexey Bayduraev } 107*d87c25e8SAlexey Bayduraev 1082171a925SArnaldo Carvalho de Melo int fdarray__filter(struct fdarray *fda, short revents, 109258e4bfcSWang Nan void (*entry_destructor)(struct fdarray *fda, int fd, void *arg), 110258e4bfcSWang Nan void *arg) 1111b85337dSArnaldo Carvalho de Melo { 1121b85337dSArnaldo Carvalho de Melo int fd, nr = 0; 1131b85337dSArnaldo Carvalho de Melo 1141b85337dSArnaldo Carvalho de Melo if (fda->nr == 0) 1151b85337dSArnaldo Carvalho de Melo return 0; 1161b85337dSArnaldo Carvalho de Melo 1171b85337dSArnaldo Carvalho de Melo for (fd = 0; fd < fda->nr; ++fd) { 11859b4412fSAlexey Budankov if (!fda->entries[fd].events) 11959b4412fSAlexey Budankov continue; 12059b4412fSAlexey Budankov 1212171a925SArnaldo Carvalho de Melo if (fda->entries[fd].revents & revents) { 1222171a925SArnaldo Carvalho de Melo if (entry_destructor) 123258e4bfcSWang Nan entry_destructor(fda, fd, arg); 1241b85337dSArnaldo Carvalho de Melo 12559b4412fSAlexey Budankov fda->entries[fd].revents = fda->entries[fd].events = 0; 1262171a925SArnaldo Carvalho de Melo continue; 1272171a925SArnaldo Carvalho de Melo } 1282171a925SArnaldo Carvalho de Melo 129d3da1f09SAlexey Budankov if (!(fda->priv[fd].flags & fdarray_flag__nonfilterable)) 1301b85337dSArnaldo Carvalho de Melo ++nr; 1311b85337dSArnaldo Carvalho de Melo } 1321b85337dSArnaldo Carvalho de Melo 13359b4412fSAlexey Budankov return nr; 1341b85337dSArnaldo Carvalho de Melo } 1351b85337dSArnaldo Carvalho de Melo 1361b85337dSArnaldo Carvalho de Melo int fdarray__poll(struct fdarray *fda, int timeout) 1371b85337dSArnaldo Carvalho de Melo { 1381b85337dSArnaldo Carvalho de Melo return poll(fda->entries, fda->nr, timeout); 1391b85337dSArnaldo Carvalho de Melo } 1401b85337dSArnaldo Carvalho de Melo 1411b85337dSArnaldo Carvalho de Melo int fdarray__fprintf(struct fdarray *fda, FILE *fp) 1421b85337dSArnaldo Carvalho de Melo { 1431b85337dSArnaldo Carvalho de Melo int fd, printed = fprintf(fp, "%d [ ", fda->nr); 1441b85337dSArnaldo Carvalho de Melo 1451b85337dSArnaldo Carvalho de Melo for (fd = 0; fd < fda->nr; ++fd) 1461b85337dSArnaldo Carvalho de Melo printed += fprintf(fp, "%s%d", fd ? ", " : "", fda->entries[fd].fd); 1471b85337dSArnaldo Carvalho de Melo 1481b85337dSArnaldo Carvalho de Melo return printed + fprintf(fp, " ]"); 1491b85337dSArnaldo Carvalho de Melo } 150