TAS
TCP Acceleration as an OS Service
libc.c
1 /*
2  * Copyright 2019 University of Washington, Max Planck Institute for
3  * Software Systems, and The University of Texas at Austin
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 #define _GNU_SOURCE
26 #define __USE_GNU
27 #include <dlfcn.h>
28 #include <pthread.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 
32 #include "internal.h"
33 #include <utils.h>
34 
35 static int (*libc_epoll_create1)(int flags) = NULL;
36 static int (*libc_epoll_ctl)(int epfd, int op, int fd,
37  struct epoll_event *event) = NULL;
38 static int (*libc_epoll_wait)(int epfd, struct epoll_event *events,
39  int maxevents, int timeout) = NULL;
40 static int (*libc_poll)(struct pollfd *fds, nfds_t nfds, int timeout);
41 static int (*libc_close)(int fd);
42 static int (*libc_dup)(int oldfd);
43 static int (*libc_dup2)(int oldfd, int newfd);
44 static int (*libc_dup3)(int oldfd, int newfd, int flags);
45 
46 static inline void ensure_init(void);
47 
48 
49 int tas_libc_epoll_create1(int flags)
50 {
51  ensure_init();
52  return libc_epoll_create1(flags);
53 }
54 
55 int tas_libc_epoll_ctl(int epfd, int op, int fd,
56  struct epoll_event *event)
57 {
58  ensure_init();
59  return libc_epoll_ctl(epfd, op, fd, event);
60 }
61 
62 int tas_libc_epoll_wait(int epfd, struct epoll_event *events,
63  int maxevents, int timeout)
64 {
65  ensure_init();
66  return libc_epoll_wait(epfd, events, maxevents, timeout);
67 }
68 
69 int tas_libc_poll(struct pollfd *fds, nfds_t nfds, int timeout)
70 {
71  ensure_init();
72  return libc_poll(fds, nfds, timeout);
73 }
74 
75 int tas_libc_close(int fd)
76 {
77  ensure_init();
78  return libc_close(fd);
79 }
80 
81 int tas_libc_dup(int oldfd)
82 {
83  ensure_init();
84  return libc_dup(oldfd);
85 }
86 
87 int tas_libc_dup2(int oldfd, int newfd)
88 {
89  ensure_init();
90  return libc_dup2(oldfd, newfd);
91 }
92 
93 int tas_libc_dup3(int oldfd, int newfd, int flags)
94 {
95  ensure_init();
96  return libc_dup3(oldfd, newfd, flags);
97 }
98 
99 
100 /******************************************************************************/
101 /* Helper functions */
102 
103 static void *bind_symbol(void *handle, const char *sym)
104 {
105  void *ptr;
106  if ((ptr = dlsym(handle, sym)) == NULL) {
107  fprintf(stderr, "tas libc lookup: dlsym failed (%s)\n", sym);
108  abort();
109  }
110  return ptr;
111 }
112 
113 static void init(void)
114 {
115  void *handle;
116 
117  if ((handle = dlopen("libc.so.6", RTLD_LAZY)) == NULL) {
118  perror("tas libc lookup: dlopen on libc failed");
119  abort();
120  }
121 
122  libc_close = bind_symbol(handle, "close");
123  libc_epoll_create1 = bind_symbol(handle, "epoll_create1");
124  libc_epoll_ctl = bind_symbol(handle, "epoll_ctl");
125  libc_epoll_wait = bind_symbol(handle, "epoll_wait");
126  libc_poll = bind_symbol(handle, "poll");
127  libc_dup = bind_symbol(handle, "dup");
128  libc_dup2 = bind_symbol(handle, "dup2");
129  libc_dup3 = bind_symbol(handle, "dup3");
130 }
131 
132 static inline void ensure_init(void)
133 {
134  static volatile uint32_t init_cnt = 0;
135  static volatile uint8_t init_done = 0;
136  static __thread uint8_t in_init = 0;
137 
138  if (init_done == 0) {
139  /* during init the socket functions will be used to connect to the kernel on
140  * a unix socket, so make sure that runs through. */
141  if (in_init) {
142  return;
143  }
144 
145  if (__sync_fetch_and_add(&init_cnt, 1) == 0) {
146  in_init = 1;
147  init();
148  in_init = 0;
149  MEM_BARRIER();
150  init_done = 1;
151  } else {
152  while (init_done == 0) {
153  pthread_yield();
154  }
155  MEM_BARRIER();
156  }
157  }
158 }
static int epfd
Definition: appif.c:80