+int
+memif_per_thread_init (memif_per_thread_main_handle_t * pt_main,
+ void *private_ctx,
+ memif_control_fd_update_t * on_control_fd_update,
+ char *app_name, memif_alloc_t * memif_alloc,
+ memif_realloc_t * memif_realloc,
+ memif_free_t * memif_free)
+{
+ memif_err_t err = MEMIF_ERR_SUCCESS;
+ int i;
+ libmemif_main_t *lm;
+
+ /* Allocate unique libmemif main */
+ if (memif_alloc != NULL)
+ lm = memif_alloc (sizeof (libmemif_main_t));
+ else
+ lm = malloc (sizeof (libmemif_main_t));
+
+ if (lm == NULL)
+ return MEMIF_ERR_NOMEM;
+
+ memset (lm, 0, sizeof (libmemif_main_t));
+
+ /* register custom memory management */
+ if (memif_alloc != NULL)
+ {
+ memif_alloc_register (lm, memif_alloc);
+ }
+ else
+ memif_alloc_register (lm, malloc);
+
+ if (memif_realloc != NULL)
+ {
+ memif_realloc_register (lm, memif_realloc);
+ }
+ else
+ memif_realloc_register (lm, realloc);
+
+ if (memif_free != NULL)
+ memif_free_register (lm, memif_free);
+ else
+ memif_free_register (lm, free);
+
+ lm->private_ctx = private_ctx;
+
+ /* set app name */
+ if (app_name != NULL)
+ {
+ uint8_t len = (strlen (app_name) > MEMIF_NAME_LEN)
+ ? strlen (app_name) : MEMIF_NAME_LEN;
+ strncpy ((char *) lm->app_name, app_name, len);
+ }
+ else
+ {
+ strncpy ((char *) lm->app_name, MEMIF_DEFAULT_APP_NAME,
+ strlen (MEMIF_DEFAULT_APP_NAME));
+ }
+
+ lm->poll_cancel_fd = -1;
+ /* register control fd update callback */
+ if (on_control_fd_update != NULL)
+ memif_control_fd_update_register (lm, on_control_fd_update);
+ else
+ {
+ /* private_ctx only used internally by memif_control_fd_update
+ * pointer to this libmemif main
+ */
+ lm->private_ctx = lm;
+ lm->epfd = epoll_create (1);
+ memif_control_fd_update_register (lm, memif_control_fd_update);
+ if ((lm->poll_cancel_fd = eventfd (0, EFD_NONBLOCK)) < 0)
+ {
+ err = errno;
+ DBG ("eventfd: %s", strerror (err));
+ return memif_syscall_error_handler (err);
+ }
+ lm->control_fd_update (lm->poll_cancel_fd, MEMIF_FD_EVENT_READ,
+ lm->private_ctx);
+ DBG ("libmemif event polling initialized");
+ }
+
+ /* Initialize lists */
+ lm->control_list_len = 2;
+ lm->interrupt_list_len = 2;
+ lm->socket_list_len = 1;
+ lm->pending_list_len = 1;
+
+ lm->control_list =
+ lm->alloc (sizeof (memif_list_elt_t) * lm->control_list_len);
+ if (lm->control_list == NULL)
+ {
+ err = MEMIF_ERR_NOMEM;
+ goto error;
+ }
+ lm->interrupt_list =
+ lm->alloc (sizeof (memif_list_elt_t) * lm->interrupt_list_len);
+ if (lm->interrupt_list == NULL)
+ {
+ err = MEMIF_ERR_NOMEM;
+ goto error;
+ }
+ lm->socket_list =
+ lm->alloc (sizeof (memif_list_elt_t) * lm->socket_list_len);
+ if (lm->socket_list == NULL)
+ {
+ err = MEMIF_ERR_NOMEM;
+ goto error;
+ }
+ lm->pending_list =
+ lm->alloc (sizeof (memif_list_elt_t) * lm->pending_list_len);
+ if (lm->pending_list == NULL)
+ {
+ err = MEMIF_ERR_NOMEM;
+ goto error;
+ }
+
+ for (i = 0; i < lm->control_list_len; i++)
+ {
+ lm->control_list[i].key = -1;
+ lm->control_list[i].data_struct = NULL;
+ }
+ for (i = 0; i < lm->interrupt_list_len; i++)
+ {
+ lm->interrupt_list[i].key = -1;
+ lm->interrupt_list[i].data_struct = NULL;
+ }
+ for (i = 0; i < lm->socket_list_len; i++)
+ {
+ lm->socket_list[i].key = -1;
+ lm->socket_list[i].data_struct = NULL;
+ }
+ for (i = 0; i < lm->pending_list_len; i++)
+ {
+ lm->pending_list[i].key = -1;
+ lm->pending_list[i].data_struct = NULL;
+ }
+
+ /* Initialize autoconnect */
+ lm->disconn_slaves = 0;
+
+ lm->timerfd = timerfd_create (CLOCK_REALTIME, TFD_NONBLOCK);
+ if (lm->timerfd < 0)
+ {
+ err = memif_syscall_error_handler (errno);
+ goto error;
+ }
+
+ lm->arm.it_value.tv_sec = MEMIF_DEFAULT_RECONNECT_PERIOD_SEC;
+ lm->arm.it_value.tv_nsec = MEMIF_DEFAULT_RECONNECT_PERIOD_NSEC;
+ lm->arm.it_interval.tv_sec = MEMIF_DEFAULT_RECONNECT_PERIOD_SEC;
+ lm->arm.it_interval.tv_nsec = MEMIF_DEFAULT_RECONNECT_PERIOD_NSEC;
+
+ if (lm->control_fd_update (lm->timerfd, MEMIF_FD_EVENT_READ,
+ lm->private_ctx) < 0)
+ {
+ DBG ("callback type memif_control_fd_update_t error!");
+ err = MEMIF_ERR_CB_FDUPDATE;
+ goto error;
+ }
+
+ *pt_main = lm;
+
+ return err;
+
+error:
+ *pt_main = lm;
+ memif_per_thread_cleanup (pt_main);
+ return err;
+}
+