예제 #1
0
int flock_open(lua_State *L) {
   const char *file_name = lua_tostring(L, 1);
   int no_block = luaT_optboolean(L, 2, 0);
   int flags = O_CLOEXEC | O_RDWR;
   if (!no_block) {
      flags |= O_CREAT;
   }
   int fd = open(file_name, flags, S_IRUSR | S_IWUSR);
   if (fd < 0) {
      if (errno == ENOENT || errno == EACCES) return 0;
      return LUA_HANDLE_ERROR(L, errno);
   }
   flags = LOCK_EX;
   if (no_block) {
      flags |= LOCK_NB;
   }
   int ret = flock(fd, flags);
   if (ret < 0) {
      close(fd);
      if ((flags & LOCK_NB) && (errno == EWOULDBLOCK)) return 0;
      return LUA_HANDLE_ERROR(L, errno);
   }
   int *handle = lua_newuserdata(L, sizeof(int));
   *handle = fd;
   luaL_getmetatable(L, "ipc.flock");
   lua_setmetatable(L, -2);
   return 1;
}
예제 #2
0
파일: map.c 프로젝트: bigdatafly/torch-ipc
int map_open(lua_State *L) {
   uint32_t num_threads = lua_tonumber(L, 1);
   if (lua_type(L, 2) != LUA_TFUNCTION) return LUA_HANDLE_ERROR_STR(L, "map arg #2 expected a function");
   map_thread_t *threads = (map_thread_t *)calloc(num_threads, sizeof(map_thread_t));
   int k = lua_gettop(L);
   for (uint32_t i = 0; i < num_threads; i++) {
      threads[i].rb = ringbuffer_create(MAX_ARG_SIZE);
      for (int j = 2; j <= k; j++) {
         int ret = rb_save_with_growth(L, j, threads[i].rb);
         if (ret) return LUA_HANDLE_ERROR(L, ret);
      }
      lua_pushinteger(L, i + 1);
      int ret = rb_save_with_growth(L, k + 1, threads[i].rb);
      if (ret) return LUA_HANDLE_ERROR(L, ret);
      lua_pop(L, 1);
      ret = pthread_create(&threads[i].thread, NULL, thread_func, &threads[i]);
      if (ret) return LUA_HANDLE_ERROR(L, ret);
   }
   map_t *map = (map_t *)lua_newuserdata(L, sizeof(map_t));
   map->num_threads = num_threads;
   map->threads = threads;
   luaL_getmetatable(L, "ipc.map");
   lua_setmetatable(L, -2);
   return 1;
}
예제 #3
0
파일: cliser.c 프로젝트: hardiku/torch-ipc
int cliser_client(lua_State *L) {
#ifdef USE_CUDA
   // sometimes cutorch is loaded late, this is a good spot to try and register...
   Lcliser_CudaInit(L);
#endif
   const char *host;
   const char *port;
   if (lua_type(L, 1) == LUA_TSTRING) {
      host = lua_tostring(L, 1);
      port = lua_tostring(L, 2);
   } else {
      host = DEFAULT_HOST;
      port = lua_tostring(L, 1);
   }
   socklen_t addrlen = sizeof(struct sockaddr);
   struct sockaddr addr;
   int ret = get_sockaddr(L, host, port, &addr, &addrlen);
   if (ret) return ret;
   struct timeval tv;
   gettimeofday(&tv, NULL);
   uint32_t t = tv.tv_sec + DEFAULT_TIMEOUT_SECONDS;
   int sock = -1;
   while (tv.tv_sec < t) {
      ret = socket(PF_INET, SOCK_STREAM, 0);
      if (ret <= 0) return LUA_HANDLE_ERROR(L, errno);
      sock = ret;
      int value = 1;
      ret = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &value, sizeof(value));
      if (ret) break;
      ret = connect(sock, &addr, addrlen);
      if (!ret) break;
      close(sock);
      sleep(1);
      gettimeofday(&tv, NULL);
   }
   if (ret) {
      close(sock);
      return LUA_HANDLE_ERROR(L, errno);
   }
   addrlen = sizeof(struct sockaddr);
   struct sockaddr bind_addr;
   ret = getsockname(sock, &bind_addr, &addrlen);
   if (ret) {
      close(sock);
      return LUA_HANDLE_ERROR(L, errno);
   }
   int use_fastpath = can_use_fastpath(L, sock, ((struct sockaddr_in *)&bind_addr)->sin_addr.s_addr, ((struct sockaddr_in *)&addr)->sin_addr.s_addr);
   client_t *client = (client_t *)calloc(1, sizeof(client_t));
   client->sock = sock;
   client->send_rb = ringbuffer_create(SEND_RECV_SIZE);
   client->recv_rb = ringbuffer_create(SEND_RECV_SIZE);
   client->ref_count = 1;
   client->copy_context.use_fastpath = use_fastpath;
   client_t **clientp = (client_t **)lua_newuserdata(L, sizeof(client_t *));
   *clientp = client;
   luaL_getmetatable(L, "ipc.client");
   lua_setmetatable(L, -2);
   return 1;
}
예제 #4
0
파일: cliser.c 프로젝트: hardiku/torch-ipc
static int sock_send_msg(lua_State *L, int index, int sock, ringbuffer_t *rb, copy_context_t *copy_context) {
   ringbuffer_push_write_pos(rb);
   int ret = rb_save(L, index, rb, 1);
   if (ret) return LUA_HANDLE_ERROR(L, ret);
   size_t len = ringbuffer_peek(rb);
   ringbuffer_pop_write_pos(rb);
   if (ret) return ret;
   ret = sock_send(sock, &len, sizeof(len), copy_context);
   if (ret < 0) return LUA_HANDLE_ERROR(L, errno);
   if (ret != sizeof(len)) return LUA_HANDLE_ERROR_STR(L, "failed to send the correct number of bytes");
   ret = sock_send(sock, ringbuffer_buf_ptr(rb), len, copy_context);
   if (ret < 0) return LUA_HANDLE_ERROR(L, errno);
   if ((size_t)ret != len) return LUA_HANDLE_ERROR_STR(L, "failed to send the correct number of bytes");
   return 0;
}
예제 #5
0
파일: map.c 프로젝트: bigdatafly/torch-ipc
int map_join(lua_State *L) {
   int rc = 0;
   int err_rc = -1;
   map_t *map = (map_t *)lua_touserdata(L, 1);
   for (uint32_t i = 0; i < map->num_threads; i++) {
      if (map->threads[i].rb) {
         int ret = pthread_join(map->threads[i].thread, NULL);
         if (ret) return LUA_HANDLE_ERROR(L, ret);
         if (map->threads[i].ret) {
            err_rc = rc;
         }
         while (ringbuffer_peek(map->threads[i].rb)) {
            rb_load(L, map->threads[i].rb);
            rc++;
         }
         ringbuffer_destroy(map->threads[i].rb);
      }
   }
   free(map->threads);
   map->threads = NULL;
   map->num_threads = 0;
   if (err_rc >= 0) {
      return LUA_HANDLE_ERROR_STR(L, lua_tostring(L, err_rc - rc));
   }
   return rc;
}
예제 #6
0
파일: cliser.c 프로젝트: hardiku/torch-ipc
static int sock_recv_msg_peek(lua_State *L, int sock, ringbuffer_t *rb) {
   size_t len;
   int ret = recv(sock, &len, sizeof(len), MSG_PEEK | MSG_DONTWAIT);
   if (ret < 0) {
      if (errno == EAGAIN || errno == EWOULDBLOCK) return 0;
      return LUA_HANDLE_ERROR(L, errno);
   }
   if (ret != sizeof(len)) return 0;
   if (len > SEND_RECV_SIZE) return LUA_HANDLE_ERROR_STR(L, "message size is too large");
   ret = recv(sock, ringbuffer_buf_ptr(rb), len, MSG_PEEK | MSG_DONTWAIT);
   if (ret < 0) {
      if (errno == EAGAIN || errno == EWOULDBLOCK) return 0;
      return LUA_HANDLE_ERROR(L, errno);
   }
   if ((size_t)ret != len) return 0;
   return ret;
}
예제 #7
0
파일: cliser.c 프로젝트: hardiku/torch-ipc
static int sock_recv_msg(lua_State *L, int sock, ringbuffer_t *rb, copy_context_t *copy_context) {
   size_t len;
   int ret = sock_recv(sock, &len, sizeof(len), copy_context);
   if (ret < 0) return LUA_HANDLE_ERROR(L, errno);
   if (ret != sizeof(len)) return LUA_HANDLE_ERROR_STR(L, "failed to recv the correct number of bytes");
   if (len > SEND_RECV_SIZE) return LUA_HANDLE_ERROR_STR(L, "message size is too large");
   ret = sock_recv(sock, ringbuffer_buf_ptr(rb), len, copy_context);
   if (ret < 0) return LUA_HANDLE_ERROR(L, errno);
   if ((size_t)ret != len) return LUA_HANDLE_ERROR_STR(L, "failed to recv the correct number of bytes");
   ringbuffer_reset_read_pos(rb);
   ringbuffer_push_write_pos(rb);
   if (ringbuffer_write(rb, NULL, ret) != (size_t)ret) {
      ringbuffer_pop_write_pos(rb);
      return LUA_HANDLE_ERROR_STR(L, "failed to write the correct number of bytes into the ringbuffer");
   }
   ret = rb_load(L, rb);
   if (ret < 0) return LUA_HANDLE_ERROR(L, ret);
   return ret;
}
예제 #8
0
파일: cliser.c 프로젝트: hardiku/torch-ipc
int cliser_server(lua_State *L) {
#ifdef USE_CUDA
   // sometimes cutorch is loaded late, this is a good spot to try and register...
   Lcliser_CudaInit(L);
#endif
   const char *host = luaL_optstring(L, 1, DEFAULT_HOST);
   int port = luaL_optinteger(L, 2, 0);
   char port_str[16];
   snprintf(port_str, 16, "%d", port);
   struct sockaddr addr;
   socklen_t addrlen = sizeof(struct sockaddr);
   int ret = get_sockaddr(L, host, port != 0 ? port_str : NULL, &addr, &addrlen);
   if (ret) return ret;
   ret = socket(PF_INET, SOCK_STREAM, 0);
   if (ret <= 0) return LUA_HANDLE_ERROR(L, errno);
   int sock = ret;
   ret = bind(sock, &addr, addrlen);
   if (ret) {
      close(sock);
      return LUA_HANDLE_ERROR(L, errno);
   }
   ret = listen(sock, 1024);
   if (ret) {
      close(sock);
      return LUA_HANDLE_ERROR(L, errno);
   }
   struct sockaddr_in sin;
   addrlen = sizeof(struct sockaddr_in);
   ret = getsockname(sock, (struct sockaddr *)&sin, &addrlen);
   if (ret) {
      close(sock);
      return LUA_HANDLE_ERROR(L, errno);
   }
   port = ntohs(sin.sin_port);
   server_t *server = (server_t *)lua_newuserdata(L, sizeof(server_t));
   memset(server, 0, sizeof(server_t));
   server->sock = sock;
   server->ip_address = sin.sin_addr.s_addr;
   luaL_getmetatable(L, "ipc.server");
   lua_setmetatable(L, -2);
   lua_pushinteger(L, port);
   return 2;
}
예제 #9
0
int flock_close(lua_State *L) {
   int *handle = lua_touserdata(L, 1);
   int fd = *handle;
   if (fd) {
      int ret = flock(fd, LOCK_UN);
      close(fd);
      *handle = 0;
      if (ret < 0) return LUA_HANDLE_ERROR(L, errno);
   }
   return 0;
}
예제 #10
0
파일: cliser.c 프로젝트: hardiku/torch-ipc
static int can_use_fastpath(lua_State *L, int sock, uint32_t bind_addr, uint32_t addr) {
#if defined(USE_CUDA) && !defined(__APPLE__)
   if (bind_addr == addr) {
      int device;
      THCudaCheck(cudaGetDevice(&device));
      int ret = send(sock, &device, sizeof(device), 0);
      if (ret < 0) {
         close(sock);
         return LUA_HANDLE_ERROR(L, errno);
      }
      int remote_device;
      ret = recv(sock, &remote_device, sizeof(remote_device), 0);
      if (ret <= 0) {
         close(sock);
         return LUA_HANDLE_ERROR(L, errno);
      }
      if (device != remote_device) {
         int can;
         THCudaCheck(cudaDeviceCanAccessPeer(&can, device, remote_device));
         if (can) {
            cudaError_t err = cudaDeviceEnablePeerAccess(remote_device, 0);
            if (err == cudaSuccess || err == cudaErrorPeerAccessAlreadyEnabled) {
               if (err == cudaErrorPeerAccessAlreadyEnabled) cudaGetLastError();
               fprintf(stderr, "INFO: torch-ipc: CUDA IPC enabled between GPU%d and GPU%d\n", device, remote_device);
               return 1;
            } else {
               fprintf(stderr, "WARN: torch-ipc: CUDA IPC disabled between GPU%d and GPU%d: %s\n", device, remote_device, cudaGetErrorString(err));
            }
         } else {
            fprintf(stderr, "INFO: torch-ipc: CUDA IPC not possible between GPU%d and GPU%d\n", device, remote_device);
         }
      }
   }
#else
   (void)L;
   (void)sock;
   (void)bind_addr;
   (void)addr;
#endif
   return 0;
}
예제 #11
0
파일: cliser.c 프로젝트: hardiku/torch-ipc
static int destroy_server(lua_State *L, server_t *server) {
   if (server->sock) {
      int ret = close(server->sock);
      if (ret) return LUA_HANDLE_ERROR(L, errno);
      server->sock = 0;
   }
   client_t *client = server->clients;
   while (client) {
      client_t *next = client->next;
      destroy_client(L, client);
      client = next;
   }
   server->clients = NULL;
   server->num_clients = 0;
   destroy_copy_context(&server->copy_context);
   return 0;
}
예제 #12
0
파일: cliser.c 프로젝트: hardiku/torch-ipc
static int get_sockaddr(lua_State *L, const char *host, const char *port, struct sockaddr *addr, socklen_t *addrlen) {
   struct addrinfo hints;
   memset(&hints, 0, sizeof(hints));
   hints.ai_family = AF_INET;
   hints.ai_socktype = SOCK_STREAM;
   hints.ai_protocol = IPPROTO_TCP;
   struct addrinfo *ai;
   int ret = getaddrinfo(host, port, &hints, &ai);
   if (ret) return LUA_HANDLE_ERROR_STR(L, gai_strerror(ret));
   if (*addrlen < ai->ai_addrlen) {
      freeaddrinfo(ai);
      return LUA_HANDLE_ERROR(L, ENOMEM);
   }
   memcpy(addr, ai->ai_addr, ai->ai_addrlen);
   *addrlen = ai->ai_addrlen;
   freeaddrinfo(ai);
   return 0;
}
예제 #13
0
static int workqueue_queue_read(lua_State *L, queue_t *queue, int doNotBlock) {
   pthread_mutex_lock(&queue->mutex);
   while (1) {
      if (queue->num_items) {
         int ret = rb_load(L, queue->rb);
         queue->num_items--;
         pthread_cond_signal(&queue->write_avail_cond);
         pthread_mutex_unlock(&queue->mutex);
         if (ret < 0) return LUA_HANDLE_ERROR(L, ret);
         return ret;
      } else if (doNotBlock) {
         break;
      } else {
         pthread_cond_wait(&queue->read_avail_cond, &queue->mutex);
      }
   }
   pthread_mutex_unlock(&queue->mutex);
   return 0;
}
예제 #14
0
파일: cliser.c 프로젝트: hardiku/torch-ipc
int cliser_server_recv_any(lua_State *L) {
   double t0 = _ipc_seconds();
   server_t *server = (server_t *)lua_touserdata(L, 1);
   const char *tag = luaL_optstring(L, 2, NULL);
   fd_set fds;
   FD_ZERO(&fds);
   int highest = -1;
   client_t *client = server->clients;
   while (client) {
      if (!tag || (client->tag && strcmp(tag, client->tag) == 0)) {
         FD_SET(client->sock, &fds);
         if (client->sock > highest) {
            highest = client->sock;
         }
      }
      client = client->next;
   }
   int ret = select(highest + 1, &fds, NULL, NULL, NULL);
   if (ret < 0) return LUA_HANDLE_ERROR(L, errno);
   client = server->clients;
   while (client) {
      if (!tag || (client->tag && strcmp(tag, client->tag) == 0)) {
         if (FD_ISSET(client->sock, &fds)) {
            ret = sock_recv_msg(L, client->sock, client->recv_rb, &server->copy_context);
            if (ret == 1) {
               server_client_t *server_client = (server_client_t *)lua_newuserdata(L, sizeof(server_client_t));
               server_client->server = server;
               server_client->client = client;
               luaL_getmetatable(L, "ipc.server.client");
               lua_setmetatable(L, -2);
               ret = 2;
            }
            break;
         }
      }
      client = client->next;
   }
   server->copy_context.rx.total_seconds += (_ipc_seconds() - t0);
   server->copy_context.rx.num_calls++;
   return ret;
}
예제 #15
0
파일: cliser.c 프로젝트: hardiku/torch-ipc
static int destroy_client(lua_State *L, client_t *client) {
   if (client->sock) {
      int ret = close(client->sock);
      if (ret) return LUA_HANDLE_ERROR(L, errno);
      client->sock = 0;
   }
   if (client->send_rb) {
      ringbuffer_destroy(client->send_rb);
      client->send_rb = NULL;
   }
   if (client->recv_rb) {
      ringbuffer_destroy(client->recv_rb);
      client->recv_rb = NULL;
   }
   destroy_copy_context(&client->copy_context);
   if (client->tag) {
      free(client->tag);
      client->tag = NULL;
   }
   free(client);
   return 0;
}
예제 #16
0
파일: cliser.c 프로젝트: hardiku/torch-ipc
static int sock_recv_raw(lua_State *L, int sock, void *ptr, size_t len, copy_context_t *copy_context) {
   int ret = sock_recv(sock, ptr, len, copy_context);
   if (ret < 0) return LUA_HANDLE_ERROR(L, errno);
   if ((size_t)ret != len) return LUA_HANDLE_ERROR_STR(L, "failed to recv the correct number of bytes");
   return 0;
}
예제 #17
0
파일: cliser.c 프로젝트: hardiku/torch-ipc
int cliser_server_clients(lua_State *L) {
   server_t *server = (server_t *)lua_touserdata(L, 1);
   uint32_t wait;
   const char *tag;
   int fi;
   int invert_order;
   if (lua_type(L, 2) == LUA_TFUNCTION) {
      wait = 0;
      fi = 2;
      if (lua_type(L, 3) == LUA_TSTRING) {
         tag = luaL_optstring(L, 3, NULL);
         invert_order = luaL_optinteger(L, 4, 0);
      } else {
         tag = NULL;
         invert_order = luaL_optinteger(L, 3, 0);
      }
   } else {
      wait = luaL_checkint(L, 2);
      if (lua_type(L, 3) != LUA_TFUNCTION) return LUA_HANDLE_ERROR_STR(L, "expected a callback function as argument #3");
      fi = 3;
      tag = NULL;
      invert_order = 0;
   }
   while (wait > server->num_clients) {
      struct sockaddr addr;
      socklen_t addrlen = sizeof(addr);
      int ret = accept(server->sock, &addr, &addrlen);
      if (ret <= 0) return LUA_HANDLE_ERROR(L, errno);
      int sock = ret;
      int value = 1;
      ret = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &value, sizeof(value));
      if (ret) return LUA_HANDLE_ERROR(L, errno);
      int use_fastpath = can_use_fastpath(L, sock, server->ip_address, ((struct sockaddr_in *)&addr)->sin_addr.s_addr);
      client_t *client = (client_t *)calloc(1, sizeof(client_t));
      client->sock = sock;
      client->send_rb = ringbuffer_create(SEND_RECV_SIZE);
      client->recv_rb = ringbuffer_create(SEND_RECV_SIZE);
      client->copy_context.use_fastpath = use_fastpath;
      insert_client(server, client);
   }
   client_t **clients = alloca(server->num_clients * sizeof(client_t*));
   client_t *client = server->clients;
   uint32_t i = 0;
   while (client) {
      if (!tag || (client->tag && strcmp(tag, client->tag) == 0)) {
         clients[i] = client;
         i++;
      }
      client = client->next;
   }
   if (invert_order) {
      qsort(clients, i, sizeof(client_t*), compare_clients_inverted);
   } else {
      qsort(clients, i, sizeof(client_t*), compare_clients);
   }
   for (uint32_t j = 0; j < i; j++) {
      lua_pushvalue(L, fi);
      server_client_t *server_client = (server_client_t *)lua_newuserdata(L, sizeof(server_client_t));
      server_client->server = server;
      server_client->client = clients[j];
      luaL_getmetatable(L, "ipc.server.client");
      lua_setmetatable(L, -2);
      lua_call(L, 1, 0);
      server_client->server = NULL;
      server_client->client = NULL;
   }
   lua_pushinteger(L, i);
   return 1;
}