OLD | NEW |
1 /* Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 /* Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 * Use of this source code is governed by a BSD-style license that can be | 2 * Use of this source code is governed by a BSD-style license that can be |
3 * found in the LICENSE file. | 3 * found in the LICENSE file. |
4 */ | 4 */ |
5 #include "nacl_io/kernel_object.h" | 5 #include "nacl_io/kernel_object.h" |
6 | 6 |
7 #include <assert.h> | 7 #include <assert.h> |
8 #include <errno.h> | 8 #include <errno.h> |
9 #include <fcntl.h> | 9 #include <fcntl.h> |
10 #include <pthread.h> | 10 #include <pthread.h> |
(...skipping 13 matching lines...) Expand all Loading... |
24 pthread_mutex_init(&process_lock_, NULL); | 24 pthread_mutex_init(&process_lock_, NULL); |
25 } | 25 } |
26 | 26 |
27 KernelObject::~KernelObject() { | 27 KernelObject::~KernelObject() { |
28 pthread_mutex_destroy(&process_lock_); | 28 pthread_mutex_destroy(&process_lock_); |
29 pthread_mutex_destroy(&kernel_lock_); | 29 pthread_mutex_destroy(&kernel_lock_); |
30 } | 30 } |
31 | 31 |
32 // Uses longest prefix to find the mount for the give path, then | 32 // Uses longest prefix to find the mount for the give path, then |
33 // acquires the mount and returns it with a relative path. | 33 // acquires the mount and returns it with a relative path. |
34 Mount* KernelObject::AcquireMountAndPath(const std::string& relpath, | 34 Error KernelObject::AcquireMountAndPath(const std::string& relpath, |
35 Path* out_path) { | 35 Mount** out_mount, |
| 36 Path* out_path) { |
| 37 *out_mount = NULL; |
| 38 *out_path = Path(); |
| 39 |
36 Path abs_path; | 40 Path abs_path; |
37 { | 41 { |
38 AutoLock lock(&process_lock_); | 42 AutoLock lock(&process_lock_); |
39 abs_path = GetAbsPathLocked(relpath); | 43 abs_path = GetAbsPathLocked(relpath); |
40 } | 44 } |
41 | 45 |
42 AutoLock lock(&kernel_lock_); | 46 AutoLock lock(&kernel_lock_); |
43 Mount* mount = NULL; | 47 Mount* mount = NULL; |
44 | 48 |
45 | |
46 // Find longest prefix | 49 // Find longest prefix |
47 size_t max = abs_path.Size(); | 50 size_t max = abs_path.Size(); |
48 for (size_t len = 0; len < abs_path.Size(); len++) { | 51 for (size_t len = 0; len < abs_path.Size(); len++) { |
49 MountMap_t::iterator it = mounts_.find(abs_path.Range(0, max - len)); | 52 MountMap_t::iterator it = mounts_.find(abs_path.Range(0, max - len)); |
50 if (it != mounts_.end()) { | 53 if (it != mounts_.end()) { |
51 out_path->Set("/"); | 54 out_path->Set("/"); |
52 out_path->Append(abs_path.Range(max - len, max)); | 55 out_path->Append(abs_path.Range(max - len, max)); |
53 mount = it->second; | 56 mount = it->second; |
54 break; | 57 break; |
55 } | 58 } |
56 } | 59 } |
57 | 60 |
58 if (NULL == mount) { | 61 if (NULL == mount) |
59 errno = ENOTDIR; | 62 return ENOTDIR; |
60 return NULL; | |
61 } | |
62 | 63 |
63 // Acquire the mount while we hold the proxy lock | 64 // Acquire the mount while we hold the proxy lock |
64 mount->Acquire(); | 65 mount->Acquire(); |
65 return mount; | 66 *out_mount = mount; |
| 67 return 0; |
66 } | 68 } |
67 | 69 |
68 void KernelObject::ReleaseMount(Mount* mnt) { | 70 void KernelObject::ReleaseMount(Mount* mnt) { |
69 AutoLock lock(&kernel_lock_); | 71 AutoLock lock(&kernel_lock_); |
70 mnt->Release(); | 72 mnt->Release(); |
71 } | 73 } |
72 | 74 |
73 KernelHandle* KernelObject::AcquireHandle(int fd) { | 75 Error KernelObject::AcquireHandle(int fd, KernelHandle** out_handle) { |
| 76 *out_handle = NULL; |
| 77 |
74 AutoLock lock(&process_lock_); | 78 AutoLock lock(&process_lock_); |
75 if (fd < 0 || fd >= static_cast<int>(handle_map_.size())) { | 79 if (fd < 0 || fd >= static_cast<int>(handle_map_.size())) |
76 errno = EBADF; | 80 return EBADF; |
77 return NULL; | |
78 } | |
79 | 81 |
80 KernelHandle* handle = handle_map_[fd]; | 82 KernelHandle* handle = handle_map_[fd]; |
81 if (NULL == handle) { | 83 if (NULL == handle) |
82 errno = EBADF; | 84 return EBADF; |
83 return NULL; | |
84 } | |
85 | 85 |
86 // Ref count while holding parent mutex | 86 // Ref count while holding parent mutex |
87 handle->Acquire(); | 87 handle->Acquire(); |
88 | 88 |
89 lock.Unlock(); | 89 lock.Unlock(); |
90 if (handle->node_) handle->mount_->AcquireNode(handle->node_); | 90 if (handle->node_) |
| 91 handle->mount_->AcquireNode(handle->node_); |
91 | 92 |
92 return handle; | 93 *out_handle = handle; |
| 94 return 0; |
93 } | 95 } |
94 | 96 |
95 void KernelObject::ReleaseHandle(KernelHandle* handle) { | 97 void KernelObject::ReleaseHandle(KernelHandle* handle) { |
96 // The handle must already be held before taking the | 98 // The handle must already be held before taking the |
97 // kernel lock. | 99 // kernel lock. |
98 if (handle->node_) handle->mount_->ReleaseNode(handle->node_); | 100 if (handle->node_) |
| 101 handle->mount_->ReleaseNode(handle->node_); |
99 | 102 |
100 AutoLock lock(&process_lock_); | 103 AutoLock lock(&process_lock_); |
101 handle->Release(); | 104 handle->Release(); |
102 } | 105 } |
103 | 106 |
104 // Helper function to properly sort FD order in the heap, forcing | |
105 // lower numbered FD to be available first. | |
106 static bool FdOrder(int i, int j) { | |
107 return i > j; | |
108 } | |
109 | |
110 int KernelObject::AllocateFD(KernelHandle* handle) { | 107 int KernelObject::AllocateFD(KernelHandle* handle) { |
111 AutoLock lock(&process_lock_); | 108 AutoLock lock(&process_lock_); |
112 int id; | 109 int id; |
113 | 110 |
114 // Acquire the handle and its mount since we are about to track it with | 111 // Acquire the handle and its mount since we are about to track it with |
115 // this FD. | 112 // this FD. |
116 handle->Acquire(); | 113 handle->Acquire(); |
117 handle->mount_->Acquire(); | 114 handle->mount_->Acquire(); |
118 | 115 |
119 // If we can recycle and FD, use that first | 116 // If we can recycle and FD, use that first |
120 if (free_fds_.size()) { | 117 if (free_fds_.size()) { |
121 id = free_fds_.front(); | 118 id = free_fds_.front(); |
122 std::pop_heap(free_fds_.begin(), free_fds_.end(), FdOrder); | 119 // Force lower numbered FD to be available first. |
| 120 std::pop_heap(free_fds_.begin(), free_fds_.end(), std::greater<int>()); |
123 free_fds_.pop_back(); | 121 free_fds_.pop_back(); |
124 handle_map_[id] = handle; | 122 handle_map_[id] = handle; |
125 } else { | 123 } else { |
126 id = handle_map_.size(); | 124 id = handle_map_.size(); |
127 handle_map_.push_back(handle); | 125 handle_map_.push_back(handle); |
128 } | 126 } |
129 return id; | 127 return id; |
130 } | 128 } |
131 | 129 |
132 void KernelObject::FreeAndReassignFD(int fd, KernelHandle* handle) { | 130 void KernelObject::FreeAndReassignFD(int fd, KernelHandle* handle) { |
(...skipping 26 matching lines...) Expand all Loading... |
159 AutoLock lock(&process_lock_); | 157 AutoLock lock(&process_lock_); |
160 | 158 |
161 // Release the mount and handle since we no longer | 159 // Release the mount and handle since we no longer |
162 // track them with this FD. | 160 // track them with this FD. |
163 KernelHandle* handle = handle_map_[fd]; | 161 KernelHandle* handle = handle_map_[fd]; |
164 handle->Release(); | 162 handle->Release(); |
165 handle->mount_->Release(); | 163 handle->mount_->Release(); |
166 | 164 |
167 handle_map_[fd] = NULL; | 165 handle_map_[fd] = NULL; |
168 free_fds_.push_back(fd); | 166 free_fds_.push_back(fd); |
169 std::push_heap(free_fds_.begin(), free_fds_.end(), FdOrder); | 167 // Force lower numbered FD to be available first. |
| 168 std::push_heap(free_fds_.begin(), free_fds_.end(), std::greater<int>()); |
170 } | 169 } |
171 | 170 |
172 Path KernelObject::GetAbsPathLocked(const std::string& path) { | 171 Path KernelObject::GetAbsPathLocked(const std::string& path) { |
173 // Generate absolute path | 172 // Generate absolute path |
174 Path abs_path(cwd_); | 173 Path abs_path(cwd_); |
175 if (path[0] == '/') { | 174 if (path[0] == '/') { |
176 abs_path = path; | 175 abs_path = path; |
177 } else { | 176 } else { |
178 abs_path = cwd_; | 177 abs_path = cwd_; |
179 abs_path.Append(path); | 178 abs_path.Append(path); |
180 } | 179 } |
181 | 180 |
182 return abs_path; | 181 return abs_path; |
183 } | 182 } |
OLD | NEW |