aboutsummaryrefslogtreecommitdiffhomepage
path: root/tensorflow/core/platform/windows
diff options
context:
space:
mode:
authorGravatar A. Unique TensorFlower <gardener@tensorflow.org>2016-10-10 10:26:22 -0800
committerGravatar TensorFlower Gardener <gardener@tensorflow.org>2016-10-10 11:35:00 -0700
commitedaf3b342db4afa1c872da541fb0ac176a4e8ef9 (patch)
treeb976073fdc2a6404cbdc3ee323a637e2e1b16846 /tensorflow/core/platform/windows
parentd1518c26530daaee854e73365bd7dfb9a2f69dbd (diff)
Merge changes from github.
Change: 135698415
Diffstat (limited to 'tensorflow/core/platform/windows')
-rw-r--r--tensorflow/core/platform/windows/env.cc113
-rw-r--r--tensorflow/core/platform/windows/net.cc131
-rw-r--r--tensorflow/core/platform/windows/port.cc99
-rw-r--r--tensorflow/core/platform/windows/windows_file_system.cc266
-rw-r--r--tensorflow/core/platform/windows/windows_file_system.h71
5 files changed, 680 insertions, 0 deletions
diff --git a/tensorflow/core/platform/windows/env.cc b/tensorflow/core/platform/windows/env.cc
new file mode 100644
index 0000000000..a2182a831c
--- /dev/null
+++ b/tensorflow/core/platform/windows/env.cc
@@ -0,0 +1,113 @@
+/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+==============================================================================*/
+
+#include "tensorflow/core/platform/env.h"
+
+#include <Shlwapi.h>
+#include <Windows.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <time.h>
+#undef LoadLibrary
+#undef ERROR
+
+#include <thread>
+#include <vector>
+
+#include "tensorflow/core/lib/core/error_codes.pb.h"
+#include "tensorflow/core/platform/load_library.h"
+#include "tensorflow/core/platform/logging.h"
+#include "tensorflow/core/platform/windows/windows_file_system.h"
+
+namespace tensorflow {
+
+namespace {
+
+class StdThread : public Thread {
+ public:
+ // name and thread_options are both ignored.
+ StdThread(const ThreadOptions& thread_options, const string& name,
+ std::function<void()> fn)
+ : thread_(fn) {}
+ ~StdThread() { thread_.join(); }
+
+ private:
+ std::thread thread_;
+};
+
+class WindowsEnv : public Env {
+ public:
+ WindowsEnv() {}
+ ~WindowsEnv() override {
+ LOG(FATAL) << "Env::Default() must not be destroyed";
+ }
+
+ bool MatchPath(const string& path, const string& pattern) override {
+ return PathMatchSpec(path.c_str(), pattern.c_str()) == S_OK;
+ }
+
+ uint64 NowMicros() override {
+ FILETIME temp;
+ GetSystemTimeAsFileTime(&temp);
+ uint64 now_ticks =
+ (uint64)temp.dwLowDateTime + ((uint64)(temp.dwHighDateTime) << 32LL);
+ return now_ticks / 10LL;
+ }
+
+ void SleepForMicroseconds(int64 micros) override { Sleep(micros / 1000); }
+
+ Thread* StartThread(const ThreadOptions& thread_options, const string& name,
+ std::function<void()> fn) override {
+ return new StdThread(thread_options, name, fn);
+ }
+
+ void SchedClosure(std::function<void()> closure) override {
+ // TODO(b/27290852): Spawning a new thread here is wasteful, but
+ // needed to deal with the fact that many `closure` functions are
+ // blocking in the current codebase.
+ std::thread closure_thread(closure);
+ closure_thread.detach();
+ }
+
+ void SchedClosureAfter(int64 micros, std::function<void()> closure) override {
+ // TODO(b/27290852): Consuming a thread here is wasteful, but this
+ // code is (currently) only used in the case where a step fails
+ // (AbortStep). This could be replaced by a timer thread
+ SchedClosure([this, micros, closure]() {
+ SleepForMicroseconds(micros);
+ closure();
+ });
+ }
+
+ Status LoadLibrary(const char* library_filename, void** handle) override {
+ return errors::Unimplemented("WindowsEnv::LoadLibrary");
+ }
+
+ Status GetSymbolFromLibrary(void* handle, const char* symbol_name,
+ void** symbol) override {
+ return errors::Unimplemented("WindowsEnv::GetSymbolFromLibrary");
+ }
+};
+
+} // namespace
+
+REGISTER_FILE_SYSTEM("", WindowsFileSystem);
+Env* Env::Default() {
+ static Env* default_env = new WindowsEnv;
+ return default_env;
+}
+
+} // namespace tensorflow
diff --git a/tensorflow/core/platform/windows/net.cc b/tensorflow/core/platform/windows/net.cc
new file mode 100644
index 0000000000..fbc0c39c9c
--- /dev/null
+++ b/tensorflow/core/platform/windows/net.cc
@@ -0,0 +1,131 @@
+/* Copyright 2016 The TensorFlow Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+==============================================================================*/
+
+#include "tensorflow/core/platform/net.h"
+
+#include <cerrno>
+#include <cstdlib>
+#include <unordered_set>
+
+#include <sys/types.h>
+#include <winsock.h>
+
+#include "tensorflow/core/lib/strings/strcat.h"
+#include "tensorflow/core/platform/logging.h"
+
+#undef ERROR
+
+namespace tensorflow {
+namespace internal {
+
+namespace {
+bool IsPortAvailable(int* port, bool is_tcp) {
+ const int protocol = is_tcp ? IPPROTO_TCP : 0;
+ const int fd = socket(AF_INET, is_tcp ? SOCK_STREAM : SOCK_DGRAM, protocol);
+
+ struct sockaddr_in addr;
+ int addr_len = static_cast<int>(sizeof(addr));
+ int actual_port;
+
+ CHECK_GE(*port, 0);
+ CHECK_LE(*port, 65535);
+ if (fd < 0) {
+ LOG(ERROR) << "socket() failed: " << strerror(errno);
+ return false;
+ }
+
+ // SO_REUSEADDR lets us start up a server immediately after it exists.
+ int one = 1;
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&one, sizeof(one)) <
+ 0) {
+ LOG(ERROR) << "setsockopt() failed: " << strerror(errno);
+ closesocket(fd);
+ return false;
+ }
+
+ // Try binding to port.
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = INADDR_ANY;
+ addr.sin_port = htons((uint16_t)*port);
+ if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
+ LOG(WARNING) << "bind(port=" << *port << ") failed: " << strerror(errno);
+ closesocket(fd);
+ return false;
+ }
+
+ // Get the bound port number.
+ if (getsockname(fd, (struct sockaddr*)&addr, &addr_len) < 0) {
+ LOG(WARNING) << "getsockname() failed: " << strerror(errno);
+ closesocket(fd);
+ return false;
+ }
+ CHECK_LE(addr_len, sizeof(addr));
+ actual_port = ntohs(addr.sin_port);
+ CHECK_GT(actual_port, 0);
+ if (*port == 0) {
+ *port = actual_port;
+ } else {
+ CHECK_EQ(*port, actual_port);
+ }
+ closesocket(fd);
+ return true;
+}
+
+const int kNumRandomPortsToPick = 100;
+const int kMaximumTrials = 1000;
+
+} // namespace
+
+int PickUnusedPortOrDie() {
+ static std::unordered_set<int> chosen_ports;
+
+ // Type of port to first pick in the next iteration.
+ bool is_tcp = true;
+ int trial = 0;
+ while (true) {
+ int port;
+ trial++;
+ CHECK_LE(trial, kMaximumTrials)
+ << "Failed to pick an unused port for testing.";
+ if (trial == 1) {
+ port = GetCurrentProcessId() % (65536 - 30000) + 30000;
+ } else if (trial <= kNumRandomPortsToPick) {
+ port = rand() % (65536 - 30000) + 30000;
+ } else {
+ port = 0;
+ }
+
+ if (chosen_ports.find(port) != chosen_ports.end()) {
+ continue;
+ }
+ if (!IsPortAvailable(&port, is_tcp)) {
+ continue;
+ }
+
+ CHECK_GT(port, 0);
+ if (!IsPortAvailable(&port, !is_tcp)) {
+ is_tcp = !is_tcp;
+ continue;
+ }
+
+ chosen_ports.insert(port);
+ return port;
+ }
+
+ return 0;
+}
+
+} // namespace internal
+} // namespace tensorflow
diff --git a/tensorflow/core/platform/windows/port.cc b/tensorflow/core/platform/windows/port.cc
new file mode 100644
index 0000000000..b08c1cf9f4
--- /dev/null
+++ b/tensorflow/core/platform/windows/port.cc
@@ -0,0 +1,99 @@
+/* Copyright 2016 The TensorFlow Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+==============================================================================*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef SNAPPY
+#include <snappy.h>
+#endif
+#include <WinSock2.h>
+
+#include "tensorflow/core/platform/cpu_info.h"
+#include "tensorflow/core/platform/demangle.h"
+#include "tensorflow/core/platform/host_info.h"
+#include "tensorflow/core/platform/init_main.h"
+#include "tensorflow/core/platform/logging.h"
+#include "tensorflow/core/platform/mem.h"
+#include "tensorflow/core/platform/snappy.h"
+#include "tensorflow/core/platform/types.h"
+
+namespace tensorflow {
+namespace port {
+
+void InitMain(const char* usage, int* argc, char*** argv) {}
+
+string Hostname() {
+ char hostname[1024];
+ gethostname(hostname, sizeof hostname);
+ hostname[sizeof hostname - 1] = 0;
+ return string(hostname);
+}
+
+int NumSchedulableCPUs() {
+ SYSTEM_INFO system_info;
+ GetSystemInfo(&system_info);
+ return system_info.dwNumberOfProcessors;
+}
+
+void* aligned_malloc(size_t size, int minimum_alignment) {
+ return _aligned_malloc(size, minimum_alignment);
+}
+
+void aligned_free(void* aligned_memory) { _aligned_free(aligned_memory); }
+
+void MallocExtension_ReleaseToSystem(std::size_t num_bytes) {
+ // No-op.
+}
+
+std::size_t MallocExtension_GetAllocatedSize(const void* p) { return 0; }
+
+void AdjustFilenameForLogging(string* filename) {
+ // Nothing to do
+}
+
+bool Snappy_Compress(const char* input, size_t length, string* output) {
+#ifdef SNAPPY
+ output->resize(snappy::MaxCompressedLength(length));
+ size_t outlen;
+ snappy::RawCompress(input, length, &(*output)[0], &outlen);
+ output->resize(outlen);
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool Snappy_GetUncompressedLength(const char* input, size_t length,
+ size_t* result) {
+#ifdef SNAPPY
+ return snappy::GetUncompressedLength(input, length, result);
+#else
+ return false;
+#endif
+}
+
+bool Snappy_Uncompress(const char* input, size_t length, char* output) {
+#ifdef SNAPPY
+ return snappy::RawUncompress(input, length, output);
+#else
+ return false;
+#endif
+}
+
+string Demangle(const char* mangled) { return mangled; }
+
+} // namespace port
+} // namespace tensorflow
diff --git a/tensorflow/core/platform/windows/windows_file_system.cc b/tensorflow/core/platform/windows/windows_file_system.cc
new file mode 100644
index 0000000000..44b26d94e8
--- /dev/null
+++ b/tensorflow/core/platform/windows/windows_file_system.cc
@@ -0,0 +1,266 @@
+/* Copyright 2015 Google Inc. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+==============================================================================*/
+
+#include <Windows.h>
+#include <direct.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <io.h>
+#include <Shlwapi.h>
+#undef StrCat
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <time.h>
+
+#include "tensorflow/core/lib/core/error_codes.pb.h"
+#include "tensorflow/core/lib/strings/strcat.h"
+#include "tensorflow/core/platform/env.h"
+#include "tensorflow/core/platform/logging.h"
+#include "tensorflow/core/platform/posix/error.h"
+#include "tensorflow/core/platform/windows/windows_file_system.h"
+
+// TODO(mrry): Prevent this Windows.h #define from leaking out of our headers.
+#undef DeleteFile
+
+namespace tensorflow {
+
+namespace {
+
+// read() based random-access
+class WindowsRandomAccessFile : public RandomAccessFile {
+ private:
+ string filename_;
+ FILE* file_;
+
+ public:
+ WindowsRandomAccessFile(const string& fname, FILE* f)
+ : filename_(fname), file_(f) {}
+ ~WindowsRandomAccessFile() override {
+ if (file_ != NULL) {
+ // Ignoring any potential errors
+ fclose(file_);
+ }
+ }
+
+ Status Read(uint64 offset, size_t n, StringPiece* result,
+ char* scratch) const override {
+ Status s;
+ char* dst = scratch;
+ int seek_result = fseek(file_, offset, SEEK_SET);
+ if (seek_result) {
+ return IOError(filename_, errno);
+ }
+ while (n > 0 && s.ok()) {
+ size_t r = fread(dst, 1, n, file_);
+ if (r > 0) {
+ dst += r;
+ n -= r;
+ } else if (r == 0) {
+ s = Status(error::OUT_OF_RANGE, "Read fewer bytes than requested");
+ } else if (errno == EINTR || errno == EAGAIN) {
+ // Retry
+ } else {
+ s = IOError(filename_, errno);
+ }
+ }
+ *result = StringPiece(scratch, dst - scratch);
+ return s;
+ }
+};
+
+class WindowsWritableFile : public WritableFile {
+ private:
+ string filename_;
+ FILE* file_;
+
+ public:
+ WindowsWritableFile(const string& fname, FILE* f)
+ : filename_(fname), file_(f) {}
+
+ ~WindowsWritableFile() override {
+ if (file_ != NULL) {
+ // Ignoring any potential errors
+ fclose(file_);
+ }
+ }
+
+ Status Append(const StringPiece& data) override {
+ size_t r = fwrite(data.data(), 1, data.size(), file_);
+ if (r != data.size()) {
+ return IOError(filename_, errno);
+ }
+ return Status::OK();
+ }
+
+ Status Close() override {
+ Status result;
+ if (fclose(file_) != 0) {
+ result = IOError(filename_, errno);
+ }
+ file_ = NULL;
+ return result;
+ }
+
+ Status Flush() override {
+ if (fflush(file_) != 0) {
+ return IOError(filename_, errno);
+ }
+ return Status::OK();
+ }
+
+ Status Sync() override {
+ Status s;
+ if (fflush(file_) != 0) {
+ s = IOError(filename_, errno);
+ }
+ return s;
+ }
+};
+
+} // namespace
+
+Status WindowsFileSystem::NewRandomAccessFile(
+ const string& fname, std::unique_ptr<RandomAccessFile>* result) {
+ string translated_fname = TranslateName(fname);
+ result->reset();
+ Status s;
+ FILE* f = fopen(translated_fname.c_str(), "r");
+ if (f == NULL) {
+ s = IOError(fname, errno);
+ } else {
+ result->reset(new WindowsRandomAccessFile(translated_fname, f));
+ }
+ return s;
+}
+
+Status WindowsFileSystem::NewWritableFile(
+ const string& fname, std::unique_ptr<WritableFile>* result) {
+ string translated_fname = TranslateName(fname);
+ Status s;
+ FILE* f = fopen(translated_fname.c_str(), "w");
+ if (f == NULL) {
+ result->reset();
+ s = IOError(fname, errno);
+ } else {
+ result->reset(new WindowsWritableFile(translated_fname, f));
+ }
+ return s;
+}
+
+Status WindowsFileSystem::NewAppendableFile(
+ const string& fname, std::unique_ptr<WritableFile>* result) {
+ string translated_fname = TranslateName(fname);
+ Status s;
+ FILE* f = fopen(translated_fname.c_str(), "a");
+ if (f == NULL) {
+ result->reset();
+ s = IOError(fname, errno);
+ } else {
+ result->reset(new WindowsWritableFile(translated_fname, f));
+ }
+ return s;
+}
+
+Status WindowsFileSystem::NewReadOnlyMemoryRegionFromFile(
+ const string& fname, std::unique_ptr<ReadOnlyMemoryRegion>* result) {
+ return errors::Unimplemented(
+ "WindowsFileSystem::NewReadOnlyMemoryRegionFromFile");
+}
+
+bool WindowsFileSystem::FileExists(const string& fname) {
+ return _access(TranslateName(fname).c_str(), 0) == 0;
+}
+
+Status WindowsFileSystem::GetChildren(const string& dir,
+ std::vector<string>* result) {
+ string translated_dir = TranslateName(dir);
+ result->clear();
+
+ WIN32_FIND_DATA find_data;
+ HANDLE find_handle = FindFirstFile(translated_dir.c_str(), &find_data);
+ if (find_handle == INVALID_HANDLE_VALUE) {
+ // TODO(mrry): Convert to a more specific error.
+ return errors::Unknown("Error code: ", GetLastError());
+ }
+ result->push_back(find_data.cFileName);
+ while (FindNextFile(find_handle, &find_data)) {
+ result->push_back(find_data.cFileName);
+ }
+ if (!FindClose(find_handle)) {
+ // TODO(mrry): Convert to a more specific error.
+ return errors::Unknown("Error closing find handle: ", GetLastError());
+ }
+ return Status::OK();
+}
+
+Status WindowsFileSystem::DeleteFile(const string& fname) {
+ Status result;
+ if (unlink(TranslateName(fname).c_str()) != 0) {
+ result = IOError(fname, errno);
+ }
+ return result;
+}
+
+Status WindowsFileSystem::CreateDir(const string& name) {
+ Status result;
+ if (_mkdir(TranslateName(name).c_str()) != 0) {
+ result = IOError(name, errno);
+ }
+ return result;
+}
+
+Status WindowsFileSystem::DeleteDir(const string& name) {
+ Status result;
+ if (_rmdir(TranslateName(name).c_str()) != 0) {
+ result = IOError(name, errno);
+ }
+ return result;
+}
+
+Status WindowsFileSystem::GetFileSize(const string& fname, uint64* size) {
+ Status s;
+ struct _stat sbuf;
+ if (_stat(TranslateName(fname).c_str(), &sbuf) != 0) {
+ *size = 0;
+ s = IOError(fname, errno);
+ } else {
+ *size = sbuf.st_size;
+ }
+ return s;
+}
+
+Status WindowsFileSystem::RenameFile(const string& src, const string& target) {
+ Status result;
+ if (rename(TranslateName(src).c_str(), TranslateName(target).c_str()) != 0) {
+ result = IOError(src, errno);
+ }
+ return result;
+}
+
+Status WindowsFileSystem::Stat(const string& fname, FileStatistics* stat) {
+ Status s;
+ struct _stat sbuf;
+ if (_stat(TranslateName(fname).c_str(), &sbuf) != 0) {
+ s = IOError(fname, errno);
+ } else {
+ stat->mtime_nsec = sbuf.st_mtime * 1e9;
+ stat->length = sbuf.st_size;
+ stat->is_directory = PathIsDirectory(TranslateName(fname).c_str());
+ }
+ return s;
+}
+
+} // namespace tensorflow \ No newline at end of file
diff --git a/tensorflow/core/platform/windows/windows_file_system.h b/tensorflow/core/platform/windows/windows_file_system.h
new file mode 100644
index 0000000000..68b391fb10
--- /dev/null
+++ b/tensorflow/core/platform/windows/windows_file_system.h
@@ -0,0 +1,71 @@
+/* Copyright 2015 Google Inc. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+==============================================================================*/
+
+#ifndef TENSORFLOW_CORE_PLATFORM_WINDOWS_WINDOWS_FILE_SYSTEM_H_
+#define TENSORFLOW_CORE_PLATFORM_WINDOWS_WINDOWS_FILE_SYSTEM_H_
+
+#include "tensorflow/core/platform/file_system.h"
+
+#ifdef PLATFORM_WINDOWS
+#undef DeleteFile
+#endif
+
+namespace tensorflow {
+
+class WindowsFileSystem : public FileSystem {
+ public:
+ WindowsFileSystem() {}
+
+ ~WindowsFileSystem() {}
+
+ Status NewRandomAccessFile(
+ const string& fname, std::unique_ptr<RandomAccessFile>* result) override;
+
+ Status NewWritableFile(const string& fname,
+ std::unique_ptr<WritableFile>* result) override;
+
+ Status NewAppendableFile(const string& fname,
+ std::unique_ptr<WritableFile>* result) override;
+
+ Status NewReadOnlyMemoryRegionFromFile(
+ const string& fname,
+ std::unique_ptr<ReadOnlyMemoryRegion>* result) override;
+
+ bool FileExists(const string& fname) override;
+
+ Status GetChildren(const string& dir, std::vector<string>* result) override;
+
+ Status Stat(const string& fname, FileStatistics* stat) override;
+
+ Status DeleteFile(const string& fname) override;
+
+ Status CreateDir(const string& name) override;
+
+ Status DeleteDir(const string& name) override;
+
+ Status GetFileSize(const string& fname, uint64* size) override;
+
+ Status RenameFile(const string& src, const string& target) override;
+
+ string TranslateName(const string& name) const override {
+ return name;
+ }
+};
+
+Status IOError(const string& context, int err_number);
+
+} // namespace tensorflow
+
+#endif // TENSORFLOW_CORE_PLATFORM_WINDOWS_WINDOWS_FILE_SYSTEM_H_