This module fails to compile with CC=clang: make[1]: Entering directory '/home/bill/linaro/chrisdrv/platform/linux-generic' CC _fdserver.lo _fdserver.c:150:17: error: cast from 'unsigned char *' to 'int *' increases required alignment from 1 to 4 [-Werror,-Wcast-align] fd_location = (int *)CMSG_DATA(control_message); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ _fdserver.c:221:18: error: cast from 'unsigned char *' to 'int *' increases required alignment from 1 to 4 [-Werror,-Wcast-align] fd_location = (int *)CMSG_DATA(control_message); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2 errors generated. Makefile:911: recipe for target '_fdserver.lo' failed make[1]: *** [_fdserver.lo] Error 1
On Fri, Aug 19, 2016 at 10:48 AM, Christophe Milard < christophe.mil...@linaro.org> wrote: > A fdserver is added and started at init time. > The role of the fdserver (file descriptor server) is to enable sharing of > file descriptors between unrelated processes: processes which wish to > share a file descriptor may register their files descriptor to the server > and processes wishing to use the shared file descriptors can do a lookup. > When registration occurs, a triple {context, key, fd} is provided to > the server. The context identifies the client and scope (i.e. shmem). > The key is implemented as a long, and can be whatever. > The server won't care as long as keys are unique. > The file descriptor can be retrieved by another process providing the same > context and key. > Files descriptors passed this way are converted on the fly during the unix > domain socket communication that occurs between the server and its clients. > This is done by using the ancillary control data part of the msg. > > Signed-off-by: Christophe Milard <christophe.mil...@linaro.org> > --- > platform/linux-generic/Makefile.am | 2 + > platform/linux-generic/_fdserver.c | 655 > +++++++++++++++++++++ > .../linux-generic/include/_fdserver_internal.h | 38 ++ > platform/linux-generic/include/odp_internal.h | 4 + > platform/linux-generic/odp_init.c | 13 + > 5 files changed, 712 insertions(+) > create mode 100644 platform/linux-generic/_fdserver.c > create mode 100644 platform/linux-generic/include/_fdserver_internal.h > > diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/ > Makefile.am > index 271f5b5..cb7c8e9 100644 > --- a/platform/linux-generic/Makefile.am > +++ b/platform/linux-generic/Makefile.am > @@ -112,6 +112,7 @@ odpdrvplatinclude_HEADERS = \ > $(srcdir)/include/odp/drv/plat/strong_types.h > > noinst_HEADERS = \ > + ${srcdir}/include/_fdserver_internal.h \ > ${srcdir}/include/odp_align_internal.h \ > ${srcdir}/include/odp_atomic_internal.h \ > ${srcdir}/include/odp_buffer_inlines.h \ > @@ -154,6 +155,7 @@ noinst_HEADERS = \ > ${srcdir}/Makefile.inc > > __LIB__libodp_linux_la_SOURCES = \ > + _fdserver.c \ > odp_atomic.c \ > odp_barrier.c \ > odp_buffer.c \ > diff --git a/platform/linux-generic/_fdserver.c b/platform/linux-generic/_ > fdserver.c > new file mode 100644 > index 0000000..75035a8 > --- /dev/null > +++ b/platform/linux-generic/_fdserver.c > @@ -0,0 +1,655 @@ > +/* Copyright (c) 2016, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +/* > + * This file implements a file descriptor sharing server enabling > + * sharing of file descriptors between processes, regardless of fork time. > + * > + * File descriptors are process scoped, but they can be "sent and > converted > + * on the fly" between processes using special unix domain socket > ancillary > + * data. > + * The receiving process gets a file descriptor "pointing" to the same > thing > + * as the one sent (but the value of the file descriptor itself may be > different > + * from the one sent). > + * Because ODP applications are responsible for creating ODP threads (i.e. > + * pthreads or linux processes), ODP has no control on the order things > happen: > + * Nothing prevent a thread A to fork B and C, and then C creating a pktio > + * which will be used by A and B to send/receive packets. > + * Assuming this pktio uses a file descriptor, the latter will need to be > + * shared between the processes, despite the "non convenient" fork time. > + * The shared memory allocator is likely to use this as well to be able to > + * share memory regardless of fork() time. > + * This server handles a table of {(context,key)<-> fd} pair, and is > + * interfaced by the following functions: > + * > + * _odp_fdserver_register_fd(context, key, fd_to_send); > + * _odp_fdserver_deregister_fd(context, key); > + * _odp_fdserver_lookup_fd(context, key); > + * > + * which are used to register/deregister or querry for file descriptor > based > + * on a context and key value couple, which has to be unique. > + * > + * Note again that the file descriptors stored here are local to this > server > + * process and get converted both when registered or looked up. > + */ > + > +#include <odp_posix_extensions.h> > +#include <odp/api/spinlock.h> > +#include <odp_internal.h> > +#include <odp_debug_internal.h> > +#include <_fdserver_internal.h> > + > +#include <stdio.h> > +#include <stdlib.h> > +#include <errno.h> > +#include <string.h> > +#include <sys/types.h> > +#include <signal.h> > +#include <sys/socket.h> > +#include <sys/un.h> > +#include <unistd.h> > +#include <inttypes.h> > +#include <sys/mman.h> > +#include <sys/wait.h> > + > +#define FDSERVER_SOCKPATH_MAXLEN 32 > +#define FDSERVER_SOCKPATH_FORMAT "/tmp/odp-%d-fdserver" > +#define FDSERVER_BACKLOG 5 > + > +#ifndef MAP_ANONYMOUS > +#define MAP_ANONYMOUS MAP_ANON > +#endif > + > +/* when accessing the client functions, clients should be mutexed: */ > +odp_spinlock_t *client_lock; > + > +/* define the tables of file descriptors handled by this server: */ > +#define FDSERVER_MAX_ENTRIES 256 > +typedef struct fdentry_s { > + fd_server_context_e context; > + uint64_t key; > + int fd; > +} fdentry_t; > +static fdentry_t fd_table[FDSERVER_MAX_ENTRIES]; > +static int fd_table_nb_entries; > + > +/* > + * define the message struct used for communication between client and > server > + * (this single message is used in both direction) > + * The file descriptors are sent out of band as ancillary data for > conversion. > + */ > +typedef struct fd_server_msg { > + int command; > + fd_server_context_e context; > + uint64_t key; > +} fdserver_msg_t; > +/* possible commands are: */ > +#define FD_REGISTER_REQ 1 /* client -> server */ > +#define FD_REGISTER_ACK 2 /* server -> client */ > +#define FD_REGISTER_NACK 3 /* server -> client */ > +#define FD_LOOKUP_REQ 4 /* client -> server */ > +#define FD_LOOKUP_ACK 5 /* server -> client */ > +#define FD_LOOKUP_NACK 6 /* server -> client */ > +#define FD_DEREGISTER_REQ 7 /* client -> server */ > +#define FD_DEREGISTER_ACK 8 /* server -> client */ > +#define FD_DEREGISTER_NACK 9 /* server -> client */ > +#define FD_SERVERSTOP_REQ 10 /* client -> server (stops) */ > + > +/* > + * Client and server function: > + * Send a fdserver_msg, possibly including a file descriptor, on the > socket > + * This function is used both by: > + * -the client (sending a FD_REGISTER_REQ with a file descriptor to be > shared, > + * or FD_LOOKUP_REQ/FD_DEREGISTER_REQ without a file descirptor) > + * -the server (sending FD_REGISTER_ACK/NACK, FD_LOOKUP_NACK, > + * FD_DEREGISTER_ACK/NACK... without a fd or a > + * FD_LOOKUP_ACK with a fd) > + * This function make use of the ancillary data (control data) to pass and > + * convert file descriptors over UNIX sockets > + * Return -1 on error, 0 on success. > + */ > +static int send_fdserver_msg(int sock, int command, > + fd_server_context_e context, uint64_t key, > + int fd_to_send) > +{ > + struct msghdr socket_message; > + struct iovec io_vector[1]; /* one msg frgmt only */ > + struct cmsghdr *control_message = NULL; > + int *fd_location; > + fdserver_msg_t msg; > + int res; > + > + char ancillary_data[CMSG_SPACE(sizeof(int))]; > + > + /* prepare the register request body (single framgent): */ > + msg.command = command; > + msg.context = context; > + msg.key = key; > + io_vector[0].iov_base = &msg; > + io_vector[0].iov_len = sizeof(fdserver_msg_t); > + > + /* initialize socket message */ > + memset(&socket_message, 0, sizeof(struct msghdr)); > + socket_message.msg_iov = io_vector; > + socket_message.msg_iovlen = 1; > + > + if (fd_to_send >= 0) { > + /* provide space for the ancillary data */ > + memset(ancillary_data, 0, CMSG_SPACE(sizeof(int))); > + socket_message.msg_control = ancillary_data; > + socket_message.msg_controllen = CMSG_SPACE(sizeof(int)); > + > + /* initialize a single ancillary data element for fd > passing */ > + control_message = CMSG_FIRSTHDR(&socket_message); > + control_message->cmsg_level = SOL_SOCKET; > + control_message->cmsg_type = SCM_RIGHTS; > + control_message->cmsg_len = CMSG_LEN(sizeof(int)); > + fd_location = (int *)CMSG_DATA(control_message); > + *fd_location = fd_to_send; > + } > + res = sendmsg(sock, &socket_message, 0); > + if (res < 0) { > + ODP_ERR("send_fdserver_msg: %s\n", strerror(errno)); > + return(-1); > + } > + > + return 0; > +} > + > +/* > + * Client and server function > + * Receive a fdserver_msg, possibly including a file descriptor, on the > + * given socket. > + * This function is used both by: > + * -the server (receiving a FD_REGISTER_REQ with a file descriptor to be > shared, > + * or FD_LOOKUP_REQ, FD_DEREGISTER_REQ without a file descirptor) > + * -the client (receiving FD_REGISTER_ACK...without a fd or a > FD_LOOKUP_ACK with > + * a fd) > + * This function make use of the ancillary data (control data) to pass and > + * convert file descriptors over UNIX sockets. > + * Return -1 on error, 0 on success. > + */ > +static int recv_fdserver_msg(int sock, int *command, > + fd_server_context_e *context, uint64_t *key, > + int *recvd_fd) > +{ > + struct msghdr socket_message; > + struct iovec io_vector[1]; /* one msg frgmt only */ > + struct cmsghdr *control_message = NULL; > + int *fd_location; > + fdserver_msg_t msg; > + char ancillary_data[CMSG_SPACE(sizeof(int))]; > + > + memset(&socket_message, 0, sizeof(struct msghdr)); > + memset(ancillary_data, 0, CMSG_SPACE(sizeof(int))); > + > + /* setup a place to fill in message contents */ > + io_vector[0].iov_base = &msg; > + io_vector[0].iov_len = sizeof(fdserver_msg_t); > + socket_message.msg_iov = io_vector; > + socket_message.msg_iovlen = 1; > + > + /* provide space for the ancillary data */ > + socket_message.msg_control = ancillary_data; > + socket_message.msg_controllen = CMSG_SPACE(sizeof(int)); > + > + /* receive the message */ > + if (recvmsg(sock, &socket_message, MSG_CMSG_CLOEXEC) < 0) { > + ODP_ERR("recv_fdserver_msg: %s\n", strerror(errno)); > + return(-1); > + } > + > + *command = msg.command; > + *context = msg.context; > + *key = msg.key; > + > + /* grab the converted file descriptor (if any) */ > + *recvd_fd = -1; > + > + if ((socket_message.msg_flags & MSG_CTRUNC) == MSG_CTRUNC) > + return 0; > + > + /* iterate ancillary elements to find the file descriptor: */ > + for (control_message = CMSG_FIRSTHDR(&socket_message); > + control_message != NULL; > + control_message = CMSG_NXTHDR(&socket_message, > control_message)) { > + if ((control_message->cmsg_level == SOL_SOCKET) && > + (control_message->cmsg_type == SCM_RIGHTS)) { > + fd_location = (int *)CMSG_DATA(control_message); > + *recvd_fd = *fd_location; > + break; > + } > + } > + > + return 0; > +} > + > +/* opens and returns a connected socket to the server */ > +static int get_socket(void) > +{ > + char sockpath[FDSERVER_SOCKPATH_MAXLEN]; > + int s_sock; /* server socket */ > + struct sockaddr_un remote; > + int len; > + > + /* construct the named socket path: */ > + snprintf(sockpath, FDSERVER_SOCKPATH_MAXLEN, > FDSERVER_SOCKPATH_FORMAT, > + odp_global_data.main_pid); > + > + s_sock = socket(AF_UNIX, SOCK_STREAM, 0); > + if (s_sock == -1) { > + ODP_ERR("cannot connect to server: %s\n", strerror(errno)); > + return(-1); > + } > + > + remote.sun_family = AF_UNIX; > + strcpy(remote.sun_path, sockpath); > + len = strlen(remote.sun_path) + sizeof(remote.sun_family); > + if (connect(s_sock, (struct sockaddr *)&remote, len) == -1) { > + ODP_ERR("cannot connect to server: %s\n", strerror(errno)); > + close(s_sock); > + return(-1); > + } > + > + return s_sock; > +} > + > +/* > + * Client function: > + * Register a file descriptor to the server. Return -1 on error. > + */ > +int _odp_fdserver_register_fd(fd_server_context_e context, uint64_t key, > + int fd_to_send) > +{ > + int s_sock; /* server socket */ > + int res; > + int command; > + int fd; > + > + odp_spinlock_lock(client_lock); > + > + ODP_DBG("FD client register: pid=%d key=%" PRIu64 ", fd=%d\n", > + getpid(), key, fd_to_send); > + > + s_sock = get_socket(); > + if (s_sock < 0) { > + odp_spinlock_unlock(client_lock); > + return(-1); > + } > + > + res = send_fdserver_msg(s_sock, FD_REGISTER_REQ, context, key, > + fd_to_send); > + if (res < 0) { > + ODP_ERR("fd registration failure\n"); > + close(s_sock); > + odp_spinlock_unlock(client_lock); > + return -1; > + } > + > + res = recv_fdserver_msg(s_sock, &command, &context, &key, &fd); > + > + if ((res < 0) || (command != FD_REGISTER_ACK)) { > + ODP_ERR("fd registration failure\n"); > + close(s_sock); > + odp_spinlock_unlock(client_lock); > + return -1; > + } > + > + close(s_sock); > + > + odp_spinlock_unlock(client_lock); > + return 0; > +} > + > +/* > + * Client function: > + * Deregister a file descriptor from the server. Return -1 on error. > + */ > +int _odp_fdserver_deregister_fd(fd_server_context_e context, uint64_t > key) > +{ > + int s_sock; /* server socket */ > + int res; > + int command; > + int fd; > + > + odp_spinlock_lock(client_lock); > + > + ODP_DBG("FD client deregister: pid=%d key=%" PRIu64 "\n", > + getpid(), key); > + > + s_sock = get_socket(); > + if (s_sock < 0) { > + odp_spinlock_unlock(client_lock); > + return(-1); > + } > + > + res = send_fdserver_msg(s_sock, FD_DEREGISTER_REQ, context, key, > -1); > + if (res < 0) { > + ODP_ERR("fd de-registration failure\n"); > + close(s_sock); > + odp_spinlock_unlock(client_lock); > + return -1; > + } > + > + res = recv_fdserver_msg(s_sock, &command, &context, &key, &fd); > + > + if ((res < 0) || (command != FD_DEREGISTER_ACK)) { > + ODP_ERR("fd de-registration failure\n"); > + close(s_sock); > + odp_spinlock_unlock(client_lock); > + return -1; > + } > + > + close(s_sock); > + > + odp_spinlock_unlock(client_lock); > + return 0; > +} > + > +/* > + * client function: > + * lookup a file descriptor from the server. return -1 on error, > + * or the file descriptor on success (>=0). > + */ > +int _odp_fdserver_lookup_fd(fd_server_context_e context, uint64_t key) > +{ > + int s_sock; /* server socket */ > + int res; > + int command; > + int fd; > + > + odp_spinlock_lock(client_lock); > + > + s_sock = get_socket(); > + if (s_sock < 0) { > + odp_spinlock_unlock(client_lock); > + return(-1); > + } > + > + res = send_fdserver_msg(s_sock, FD_LOOKUP_REQ, context, key, -1); > + if (res < 0) { > + ODP_ERR("fd lookup failure\n"); > + close(s_sock); > + odp_spinlock_unlock(client_lock); > + return -1; > + } > + > + res = recv_fdserver_msg(s_sock, &command, &context, &key, &fd); > + > + if ((res < 0) || (command != FD_LOOKUP_ACK)) { > + ODP_ERR("fd lookup failure\n"); > + close(s_sock); > + odp_spinlock_unlock(client_lock); > + return -1; > + } > + > + close(s_sock); > + ODP_DBG("FD client lookup: pid=%d, key=%" PRIu64 ", fd=%d\n", > + getpid(), key, fd); > + > + odp_spinlock_unlock(client_lock); > + return fd; > +} > + > +/* > + * request server terminaison: > + */ > +static int stop_server(void) > +{ > + int s_sock; /* server socket */ > + int res; > + > + odp_spinlock_lock(client_lock); > + > + ODP_DBG("FD sending server stop request\n"); > + > + s_sock = get_socket(); > + if (s_sock < 0) { > + odp_spinlock_unlock(client_lock); > + return(-1); > + } > + > + res = send_fdserver_msg(s_sock, FD_SERVERSTOP_REQ, 0, 0, -1); > + if (res < 0) { > + ODP_ERR("fd stop request failure\n"); > + close(s_sock); > + odp_spinlock_unlock(client_lock); > + return -1; > + } > + > + close(s_sock); > + > + odp_spinlock_unlock(client_lock); > + return 0; > +} > + > +/* > + * server function > + * receive a client request and handle it. > + * Always returns 0 unless a stop request is received. > + */ > +static int handle_request(int client_sock) > +{ > + int command; > + fd_server_context_e context; > + uint64_t key; > + int fd; > + int i; > + > + /* get a client request: */ > + recv_fdserver_msg(client_sock, &command, &context, &key, &fd); > + switch (command) { > + case FD_REGISTER_REQ: > + if ((fd < 0) || (context >= FD_SRV_CTX_END)) { > + ODP_ERR("Invalid register fd or context\n"); > + send_fdserver_msg(client_sock, FD_REGISTER_NACK, > + FD_SRV_CTX_NA, 0, -1); > + return 0; > + } > + > + /* store the file descriptor in table: */ > + if (fd_table_nb_entries < FDSERVER_MAX_ENTRIES) { > + fd_table[fd_table_nb_entries].context = context; > + fd_table[fd_table_nb_entries].key = key; > + fd_table[fd_table_nb_entries++].fd = fd; > + ODP_DBG("storing {ctx=%d, key=%" PRIu64 > "}->fd=%d\n", > + context, key, fd); > + } else { > + ODP_ERR("FD table full\n"); > + send_fdserver_msg(client_sock, FD_REGISTER_NACK, > + FD_SRV_CTX_NA, 0, -1); > + return 0; > + } > + > + send_fdserver_msg(client_sock, FD_REGISTER_ACK, > + FD_SRV_CTX_NA, 0, -1); > + break; > + > + case FD_LOOKUP_REQ: > + if (context >= FD_SRV_CTX_END) { > + ODP_ERR("invalid lookup context\n"); > + send_fdserver_msg(client_sock, FD_LOOKUP_NACK, > + FD_SRV_CTX_NA, 0, -1); > + return 0; > + } > + > + /* search key in table and sent reply: */ > + for (i = 0; i < fd_table_nb_entries; i++) { > + if ((fd_table[i].context == context) && > + (fd_table[i].key == key)) { > + fd = fd_table[i].fd; > + ODP_DBG("lookup {ctx=%d," > + " key=%" PRIu64 "}->fd=%d\n", > + context, key, fd); > + send_fdserver_msg(client_sock, > + FD_LOOKUP_ACK, context, > key, > + fd); > + return 0; > + } > + } > + > + /* context+key not found... send nack */ > + send_fdserver_msg(client_sock, FD_LOOKUP_NACK, context, > key, > + -1); > + break; > + > + case FD_DEREGISTER_REQ: > + if (context >= FD_SRV_CTX_END) { > + ODP_ERR("invalid deregister context\n"); > + send_fdserver_msg(client_sock, FD_DEREGISTER_NACK, > + FD_SRV_CTX_NA, 0, -1); > + return 0; > + } > + > + /* search key in table and remove it if found, and reply: > */ > + for (i = 0; i < fd_table_nb_entries; i++) { > + if ((fd_table[i].context == context) && > + (fd_table[i].key == key)) { > + ODP_DBG("drop {ctx=%d," > + " key=%" PRIu64 "}->fd=%d\n", > + context, key, fd_table[i].fd); > + close(fd_table[i].fd); > + fd_table[i] = fd_table[--fd_table_nb_ > entries]; > + send_fdserver_msg(client_sock, > + FD_DEREGISTER_ACK, > + context, key, -1); > + return 0; > + } > + } > + > + /* key not found... send nack */ > + send_fdserver_msg(client_sock, FD_DEREGISTER_NACK, > + context, key, -1); > + break; > + > + case FD_SERVERSTOP_REQ: > + ODP_DBG("Stoping FD server\n"); > + return 1; > + > + default: > + ODP_ERR("Unexpected request\n"); > + break; > + } > + return 0; > +} > + > +/* > + * server function > + * loop forever, handling client requests one by one > + */ > +static void wait_requests(int sock) > +{ > + int c_socket; /* client connection */ > + unsigned int addr_sz; > + struct sockaddr_un remote; > + > + for (;;) { > + addr_sz = sizeof(remote); > + c_socket = accept(sock, (struct sockaddr *)&remote, > &addr_sz); > + if (c_socket == -1) { > + ODP_ERR("wait_requests: %s\n", > strerror(errno)); > + return; > + } > + > + if (handle_request(c_socket)) > + break; > + close(c_socket); > + } > + close(c_socket); > +} > + > +/* > + * Create a unix domain socket and fork a process to listen to incoming > + * requests. > + */ > +int _odp_fdserver_init_global(void) > +{ > + char sockpath[FDSERVER_SOCKPATH_MAXLEN]; > + int sock; > + struct sockaddr_un local; > + pid_t server_pid; > + int res; > + > + /* create the client spinlock that any client can see: */ > + client_lock = mmap(NULL, sizeof(odp_spinlock_t), PROT_READ | > PROT_WRITE, > + MAP_SHARED | MAP_ANONYMOUS, -1, 0); > + > + odp_spinlock_init(client_lock); > + > + /* construct the server named socket path: */ > + snprintf(sockpath, FDSERVER_SOCKPATH_MAXLEN, > FDSERVER_SOCKPATH_FORMAT, > + odp_global_data.main_pid); > + > + /* create UNIX domain socket: */ > + sock = socket(AF_UNIX, SOCK_STREAM, 0); > + if (sock == -1) { > + ODP_ERR("_odp_fdserver_init_global: %s\n", > strerror(errno)); > + return(-1); > + } > + > + /* remove previous named socket if it already exists: */ > + unlink(sockpath); > + > + /* bind to new named socket: */ > + local.sun_family = AF_UNIX; > + strncpy(local.sun_path, sockpath, sizeof(local.sun_path)); > + res = bind(sock, (struct sockaddr *)&local, sizeof(struct > sockaddr_un)); > + if (res == -1) { > + ODP_ERR("_odp_fdserver_init_global: %s\n", > strerror(errno)); > + close(sock); > + return(-1); > + } > + > + /* listen for incoming conections: */ > + if (listen(sock, FDSERVER_BACKLOG) == -1) { > + ODP_ERR("_odp_fdserver_init_global: %s\n", > strerror(errno)); > + close(sock); > + return(-1); > + } > + > + /* fork a server process: */ > + server_pid = fork(); > + if (server_pid == -1) { > + ODP_ERR("Could not fork!\n"); > + close(sock); > + return(-1); > + } > + > + if (server_pid == 0) { /*child */ > + /* TODO: pin the server on appropriate service cpu mask */ > + /* when (if) we can agree on the usage of service mask */ > + > + wait_requests(sock); /* Returns when server is stopped */ > + close(sock); > + exit(0); > + } > + > + /* parent */ > + close(sock); > + return 0; > +} > + > +/* > + * Terminate the server > + */ > +int _odp_fdserver_term_global(void) > +{ > + int status; > + char sockpath[FDSERVER_SOCKPATH_MAXLEN]; > + > + /* close the server and wait for child terminaison*/ > + stop_server(); > + wait(&status); > + > + /* construct the server named socket path: */ > + snprintf(sockpath, FDSERVER_SOCKPATH_MAXLEN, > FDSERVER_SOCKPATH_FORMAT, > + odp_global_data.main_pid); > + > + /* delete the UNIX domain socket: */ > + unlink(sockpath); > + > + return 0; > +} > diff --git a/platform/linux-generic/include/_fdserver_internal.h > b/platform/linux-generic/include/_fdserver_internal.h > new file mode 100644 > index 0000000..480ac02 > --- /dev/null > +++ b/platform/linux-generic/include/_fdserver_internal.h > @@ -0,0 +1,38 @@ > +/* Copyright (c) 2016, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +#ifndef _FD_SERVER_INTERNAL_H > +#define _FD_SERVER_INTERNAL_H > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +/* > + * the following enum defines the different contextes by which the > + * FD server may be used: In the FD server, the keys used to > store/retrieve > + * a file descriptor are actually context based: > + * Both the context and the key are stored at fd registration time, > + * and both the context and the key are used to retrieve a fd. > + * In other words a context identifies a FD server usage, so that > different > + * unrelated fd server users do not have to guarantee key unicity between > + * them. > + */ > +typedef enum fd_server_context { > + FD_SRV_CTX_NA, /* Not Applicable */ > + FD_SRV_CTX_END, /* upper enum limit */ > +} fd_server_context_e; > + > +int _odp_fdserver_register_fd(fd_server_context_e context, uint64_t key, > + int fd); > +int _odp_fdserver_deregister_fd(fd_server_context_e context, uint64_t > key); > +int _odp_fdserver_lookup_fd(fd_server_context_e context, uint64_t key); > + > +#ifdef __cplusplus > +} > +#endif > + > +#endif > diff --git a/platform/linux-generic/include/odp_internal.h > b/platform/linux-generic/include/odp_internal.h > index 8bad450..fd770b5 100644 > --- a/platform/linux-generic/include/odp_internal.h > +++ b/platform/linux-generic/include/odp_internal.h > @@ -54,6 +54,7 @@ enum init_stage { > CPUMASK_INIT, > TIME_INIT, > SYSINFO_INIT, > + FDSERVER_INIT, > SHM_INIT, > THREAD_INIT, > POOL_INIT, > @@ -119,6 +120,9 @@ int odp_tm_term_global(void); > int _odp_int_name_tbl_init_global(void); > int _odp_int_name_tbl_term_global(void); > > +int _odp_fdserver_init_global(void); > +int _odp_fdserver_term_global(void); > + > int cpuinfo_parser(FILE *file, system_info_t *sysinfo); > uint64_t odp_cpu_hz_current(int id); > > diff --git a/platform/linux-generic/odp_init.c > b/platform/linux-generic/odp_init.c > index f534759..ec84fd0 100644 > --- a/platform/linux-generic/odp_init.c > +++ b/platform/linux-generic/odp_init.c > @@ -51,6 +51,12 @@ int odp_init_global(odp_instance_t *instance, > } > stage = SYSINFO_INIT; > > + if (_odp_fdserver_init_global()) { > + ODP_ERR("ODP fdserver init failed.\n"); > + goto init_failed; > + } > + stage = FDSERVER_INIT; > + > if (odp_shm_init_global()) { > ODP_ERR("ODP shm init failed.\n"); > goto init_failed; > @@ -218,6 +224,13 @@ int _odp_term_global(enum init_stage stage) > } > /* Fall through */ > > + case FDSERVER_INIT: > + if (_odp_fdserver_term_global()) { > + ODP_ERR("ODP fdserver term failed.\n"); > + rc = -1; > + } > + /* Fall through */ > + > case SYSINFO_INIT: > if (odp_system_info_term()) { > ODP_ERR("ODP system info term failed.\n"); > -- > 2.7.4 > >