Commit df1b4f64 by Tianqi Chen Committed by GitHub

[IOS] Improve the iOS RPC with exclusive filesys lock (#981)

parent 91515322
......@@ -139,6 +139,7 @@ xcuserdata/
.DS_Store
tags
cscope*
*.lock
# vim temporary files
*.swp
......
......@@ -59,7 +59,6 @@ def test_rpc_module():
# Start RPC test server that contains the compiled library.
server = xcode.popen_test_rpc(proxy_host, proxy_port, key,
destination=destination,
options=['-quiet'],
libs=[path_dso1, path_dso2])
# connect to the proxy
......
......@@ -320,7 +320,7 @@ typedef void (*TVMPackedCFuncFinalizer)(void* resource_handle);
* TVM call this function to get the extension functions
* The declarer will call register_func to register function and their name.
*
* \param resource_func_handle The register function
* \param register_func_handle The register function
* \return 0 if success, -1 if failure happens
*/
typedef int (*TVMExtensionFuncDeclarer)(TVMFunctionHandle register_func_handle);
......
......@@ -688,11 +688,10 @@ inline TVMType String2TVMType(std::string s) {
LOG(FATAL) << "unknown type " << s;
}
char* xdelim; // emulate sscanf("%ux%u", bits, lanes)
unsigned bits = strtoul(scan, &xdelim, 10);
if (bits != 0) t.bits = static_cast<uint8_t>(bits);
uint8_t bits = static_cast<uint8_t>(strtoul(scan, &xdelim, 10));
if (bits != 0) t.bits = bits;
if (*xdelim == 'x') {
unsigned lanes = strtoul(xdelim + 1, nullptr, 10);
t.lanes = static_cast<uint16_t>(lanes);
t.lanes = static_cast<uint16_t>(strtoul(xdelim + 1, nullptr, 10));
}
return t;
}
......
......@@ -392,7 +392,7 @@ class Proxy(object):
port=9091,
port_end=9199,
web_port=0,
timeout_client=240,
timeout_client=600,
timeout_server=600,
index_page=None,
resource_files=None):
......
......@@ -2,6 +2,7 @@
from __future__ import absolute_import as _abs
import os
import tempfile
import fcntl
import shutil
class TempDirectory(object):
......@@ -38,7 +39,7 @@ class TempDirectory(object):
return os.path.join(self.temp_dir, name)
def listdir(self):
""""List contents in the dir.
"""List contents in the dir.
Returns
-------
......@@ -47,6 +48,7 @@ class TempDirectory(object):
"""
return os.listdir(self.temp_dir)
def tempdir():
"""Create temp dir which deletes the contents when exit.
......@@ -56,3 +58,38 @@ def tempdir():
The temp directory object
"""
return TempDirectory()
class FileLock(object):
"""File lock object
Parameters
----------
path : str
The path to the lock
"""
def __init__(self, path):
self.lock_file = open(path, "w")
fcntl.lockf(self.lock_file, fcntl.LOCK_EX)
def release(self):
"""Release the lock"""
if self.lock_file:
fcntl.lockf(self.lock_file, fcntl.LOCK_UN)
self.lock_file.close()
self.lock_file = None
def filelock(path):
"""Create a file lock which locks on path
Parameters
----------
path : str
The path to the lock
Returns
-------
lock : File lock object
"""
return FileLock(path)
......@@ -146,6 +146,28 @@ def compile_metal(code, path_target=None, sdk="macosx"):
return libbin
class XCodeRPCServer(object):
"""Wrapper for RPC server
Parameters
----------
cmd : list of str
The command to run
lock: FileLock
Lock on the path
"""
def __init__(self, cmd, lock):
self.proc = subprocess.Popen(cmd)
self.lock = lock
def join(self):
"""Wait server to finish and release its resource
"""
self.proc.wait()
self.lock.release()
def popen_test_rpc(host,
port,
key,
......@@ -190,6 +212,10 @@ def popen_test_rpc(host,
if not os.path.exists(proj_path):
raise RuntimeError("Cannot find tvmrpc.xcodeproj in %s," +
(" please set env TVM_IOS_RPC_ROOT correctly" % rpc_root))
# Lock the path so only one file can run
lock = util.filelock(os.path.join(rpc_root, "ios_rpc.lock"))
with open(os.path.join(rpc_root, "rpc_config.txt"), "w") as fo:
fo.write("%s %d %s\n" % (host, port, key))
libs = libs if libs else []
......@@ -203,11 +229,5 @@ def popen_test_rpc(host,
if options:
cmd += options
cmd += ["test"]
if "-quiet" in options:
with open(os.devnull, 'w') as devnull:
proc = subprocess.Popen(cmd,
stderr=subprocess.STDOUT,
stdout=devnull)
else:
proc = subprocess.Popen(cmd)
return proc
return XCodeRPCServer(cmd, lock)
......@@ -57,7 +57,7 @@ class GraphRuntime : public ModuleNode {
}
/*!
* \brief Initialize the graph executor with graph and context.
* \param graph The execution graph.
* \param graph_json The execution graph.
* \param module The module containing the compiled functions.
* \param ctx The context where the graph should sit on
*/
......@@ -94,7 +94,7 @@ class GraphRuntime : public ModuleNode {
/*!
* \brief set index-th input to the graph.
* \param index The input index.
* \param data The input data.
* \param data_in The input data.
*/
void SetInput(int index, DLTensor* data_in) {
CHECK_LT(static_cast<size_t>(index), input_nodes_.size());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment