Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. |
| 3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
| 4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
| 5 */ | 5 */ |
| 6 #include "base/KernelProxy.h" | 6 #include "base/KernelProxy.h" |
| 7 #include <assert.h> | 7 #include <assert.h> |
| 8 #ifndef __GLIBC__ | 8 #ifndef __GLIBC__ |
| 9 #include <nacl-mounts/net/newlib_compat.h> | 9 #include <nacl-mounts/net/newlib_compat.h> |
| 10 #else | 10 #else |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 28 #define MAXPATHLEN 256 | 28 #define MAXPATHLEN 256 |
| 29 #endif | 29 #endif |
| 30 | 30 |
| 31 static const int64_t kMicrosecondsPerSecond = 1000 * 1000; | 31 static const int64_t kMicrosecondsPerSecond = 1000 * 1000; |
| 32 static const int64_t kNanosecondsPerMicrosecond = 1000; | 32 static const int64_t kNanosecondsPerMicrosecond = 1000; |
| 33 | 33 |
| 34 KernelProxy::KernelProxy() { | 34 KernelProxy::KernelProxy() { |
| 35 if (pthread_mutex_init(&kp_lock_, NULL)) assert(0); | 35 if (pthread_mutex_init(&kp_lock_, NULL)) assert(0); |
| 36 cwd_ = Path("/"); | 36 cwd_ = Path("/"); |
| 37 mm_.Init(); | 37 mm_.Init(); |
| 38 | |
| 39 // Setup file descriptors 0, 1, and 2 for STDIN, STDOUT, and STDERR | 38 // Setup file descriptors 0, 1, and 2 for STDIN, STDOUT, and STDERR |
| 40 int ret = mkdir("/dev", 0777); | 39 int ret = mkdir("/dev", 0777); |
| 41 assert(ret == 0); | 40 assert(ret == 0); |
| 42 DevMount* dev_mount = new DevMount(); | 41 DevMount* dev_mount = new DevMount(); |
| 43 ret = mm_.AddMount(dev_mount, "/dev"); | 42 ret = mm_.AddMount(dev_mount, "/dev"); |
| 44 assert(ret == 0); | 43 assert(ret == 0); |
| 45 ret = mkdir("/dev/fd", 0777); | 44 ret = mkdir("/dev/fd", 0777); |
| 46 assert(ret == 0); | 45 assert(ret == 0); |
| 47 ConsoleMount *console_mount = new ConsoleMount(); | 46 ConsoleMount *console_mount = new ConsoleMount(); |
| 48 ret = mm_.AddMount(console_mount, "/dev/fd"); | 47 ret = mm_.AddMount(console_mount, "/dev/fd"); |
| 49 assert(ret == 0); | 48 assert(ret == 0); |
| 50 int fd = open("/dev/fd/0", O_CREAT | O_RDWR, 0); | 49 int fd = open("/dev/fd/0", O_CREAT | O_RDWR, 0); |
| 51 assert(fd == 0); | 50 assert(fd == 0); |
| 52 fd = open("/dev/fd/1", O_CREAT | O_RDWR, 0); | 51 fd = open("/dev/fd/1", O_CREAT | O_RDWR, 0); |
| 53 assert(fd == 1); | 52 assert(fd == 1); |
| 54 fd = open("/dev/fd/2", O_CREAT | O_RDWR, 0); | 53 fd = open("/dev/fd/2", O_CREAT | O_RDWR, 0); |
| 55 assert(fd == 2); | 54 assert(fd == 2); |
| 55 socket_subsystem_ = NULL; | |
| 56 } | 56 } |
| 57 | 57 |
| 58 void KernelProxy::SetSocketSubSystem(BaseSocketSubSystem* bss) { | 58 void KernelProxy::SetSocketSubSystem(BaseSocketSubSystem* bss) { |
| 59 socket_subsystem_ = bss; | 59 socket_subsystem_ = bss; |
| 60 } | 60 } |
| 61 | 61 |
| 62 void KernelProxy::RemoveSocket(int fd) { | 62 void KernelProxy::RemoveSocket(int fd) { |
| 63 this->close(fd); | 63 this->close(fd); |
| 64 } | 64 } |
| 65 | 65 |
| 66 int KernelProxy::AddSocket(Socket* stream) { | 66 int KernelProxy::AddSocket(Socket* stream) { |
| 67 SimpleAutoLock lock(&kp_lock_); | 67 SimpleAutoLock lock(&kp_lock_); |
| 68 | 68 |
| 69 // Setup file handle. | 69 // Setup file handle. |
| 70 int handle_slot = open_files_.Alloc(); | 70 int handle_slot = open_files_.Alloc(); |
| 71 int fd = fds_.Alloc(); | 71 int fd = fds_.Alloc(); |
| 72 FileDescriptor* file = fds_.At(fd); | 72 FileDescriptor* file = fds_.At(fd); |
| 73 file->handle = handle_slot; | 73 file->handle = handle_slot; |
| 74 FileHandle* handle = open_files_.At(handle_slot); | 74 FileHandle* handle = open_files_.At(handle_slot); |
| 75 | 75 |
| 76 // init should be safe because we have the kernel proxy lock | 76 // init should be safe because we have the kernel proxy lock |
| 77 if (pthread_mutex_init(&handle->lock, NULL)) assert(0); | 77 if (pthread_mutex_init(&handle->lock, NULL)) assert(0); |
| 78 | 78 |
| 79 handle->mount = reinterpret_cast<Mount*>(NULL); | 79 handle->mount = reinterpret_cast<Mount*>(NULL); |
| 80 handle->stream = reinterpret_cast<Socket*>(NULL); | 80 handle->stream = stream; |
| 81 handle->use_count = 1; | 81 handle->use_count = 1; |
| 82 | 82 |
| 83 return fd; | 83 return fd; |
| 84 } | 84 } |
| 85 | 85 |
| 86 KernelProxy *KernelProxy::KPInstance() { | 86 KernelProxy *KernelProxy::KPInstance() { |
| 87 pthread_once(&kp_once_, Instantiate); | 87 pthread_once(&kp_once_, Instantiate); |
| 88 return kp_instance_; | 88 return kp_instance_; |
| 89 } | 89 } |
| 90 | 90 |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 421 | 421 |
| 422 int KernelProxy::kill(pid_t pid, int sig) { | 422 int KernelProxy::kill(pid_t pid, int sig) { |
| 423 errno = ENOSYS; | 423 errno = ENOSYS; |
| 424 fprintf(stderr, "kill has not been implemented!\n"); | 424 fprintf(stderr, "kill has not been implemented!\n"); |
| 425 assert(0); | 425 assert(0); |
| 426 return -1; | 426 return -1; |
| 427 } | 427 } |
| 428 | 428 |
| 429 int KernelProxy::getdents(int fd, void *buf, unsigned int count) { | 429 int KernelProxy::getdents(int fd, void *buf, unsigned int count) { |
| 430 FileHandle* handle; | 430 FileHandle* handle; |
| 431 | |
| 432 // check if fd is valid and handle exists | 431 // check if fd is valid and handle exists |
| 433 if (!(handle = GetFileHandle(fd))) { | 432 if (!(handle = GetFileHandle(fd))) { |
| 434 errno = EBADF; | 433 errno = EBADF; |
| 435 return -1; | 434 return -1; |
| 436 } | 435 } |
| 437 | 436 |
| 438 SimpleAutoLock(&handle->lock); | 437 SimpleAutoLock(&handle->lock); |
| 439 | 438 |
| 440 int ret = handle->mount->Getdents(handle->node, handle->offset, | 439 int ret = handle->mount->Getdents(handle->node, handle->offset, |
| 441 (struct dirent*)buf, count); | 440 (struct dirent*)buf, count); |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 471 | 470 |
| 472 int KernelProxy::dup2(int fd, int newfd) { | 471 int KernelProxy::dup2(int fd, int newfd) { |
| 473 SimpleAutoLock lock(&kp_lock_); | 472 SimpleAutoLock lock(&kp_lock_); |
| 474 int handle_slot = fds_.At(fd)->handle; | 473 int handle_slot = fds_.At(fd)->handle; |
| 475 if (fds_.AllocAt(fd) != fd) return -1; | 474 if (fds_.AllocAt(fd) != fd) return -1; |
| 476 FileDescriptor* file = fds_.At(newfd); | 475 FileDescriptor* file = fds_.At(newfd); |
| 477 file->handle = handle_slot; | 476 file->handle = handle_slot; |
| 478 return 0; | 477 return 0; |
| 479 } | 478 } |
| 480 | 479 |
| 481 int KernelProxy::IsReady(int nfds, fd_set* fds, | 480 int KernelProxy::IsReady(int nfds, fd_set* fds, |
|
Evgeniy Stepanov
2012/06/15 12:31:47
please add a comment about the meaning of return v
| |
| 482 bool (Socket::*is_ready)(), bool apply) { | 481 bool (Socket::*is_ready)(), bool apply) { |
| 483 if (!fds) | 482 if (!fds) |
| 484 return 0; | 483 return 0; |
| 485 | 484 |
| 486 int nset = 0; | 485 int nset = 0; |
| 487 for (int i = 0; i < nfds; i++) { | 486 for (int i = 0; i < nfds; i++) { |
| 488 if (FD_ISSET(i, fds)) { | 487 if (FD_ISSET(i, fds)) { |
| 489 Socket* stream = GetFileHandle(i) > 0 ? | 488 FileHandle* h = GetFileHandle(i); |
| 490 GetFileHandle(i)->stream : NULL; | 489 if (h == NULL) { |
| 491 if (!stream) | |
| 492 return -1; | 490 return -1; |
| 491 } | |
| 492 Socket* stream = h->stream; | |
|
Evgeniy Stepanov
2012/06/15 12:31:47
You've lost the check for (!stream).
vissi
2012/06/15 13:03:20
Fixed.
| |
| 493 if ((stream->*is_ready)()) { | 493 if ((stream->*is_ready)()) { |
| 494 if (!apply) | 494 if (!apply) |
| 495 return 1; | 495 return 1; |
| 496 else | 496 else |
| 497 nset++; | 497 nset++; |
| 498 } else { | 498 } else { |
| 499 if (apply) | 499 if (apply) |
| 500 FD_CLR(i, fds); | 500 FD_CLR(i, fds); |
| 501 } | 501 } |
| 502 } | 502 } |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 845 handle->use_count = 1; | 845 handle->use_count = 1; |
| 846 return fd; | 846 return fd; |
| 847 } | 847 } |
| 848 | 848 |
| 849 int KernelProxy::accept(int sockfd, struct sockaddr *addr, | 849 int KernelProxy::accept(int sockfd, struct sockaddr *addr, |
| 850 socklen_t* addrlen) { | 850 socklen_t* addrlen) { |
| 851 if (GetFileHandle(sockfd) == 0) | 851 if (GetFileHandle(sockfd) == 0) |
| 852 return EBADF; | 852 return EBADF; |
| 853 Socket* ret = socket_subsystem_->accept(GetFileHandle(sockfd)->stream, | 853 Socket* ret = socket_subsystem_->accept(GetFileHandle(sockfd)->stream, |
| 854 addr, addrlen); | 854 addr, addrlen); |
| 855 if (ret) | 855 if (ret) { |
| 856 struct sockaddr_in* iaddr = (struct sockaddr_in*) addr; | |
| 857 iaddr->sin_family = AF_INET; | |
| 858 iaddr->sin_port = 9000; | |
|
Evgeniy Stepanov
2012/06/15 12:31:47
Why???
vissi
2012/06/15 13:03:20
Well, we need to set some address family for the c
Evgeniy Stepanov
2012/06/15 13:13:53
Move this to SocketSubsytem (or below), and query
vissi
2012/06/18 09:54:48
Thanks to dpolukhin@ for implementation details.
| |
| 856 return AddSocket(ret); | 859 return AddSocket(ret); |
| 857 else | 860 } else { |
| 858 return -1; | 861 return -1; |
| 862 } | |
| 859 } | 863 } |
| 860 | 864 |
| 861 int KernelProxy::bind(int sockfd, const struct sockaddr *addr, | 865 int KernelProxy::bind(int sockfd, const struct sockaddr *addr, |
| 862 socklen_t addrlen) { | 866 socklen_t addrlen) { |
| 863 if (GetFileHandle(sockfd) == 0) | 867 if (GetFileHandle(sockfd) == 0) |
| 864 return EBADF; | 868 return EBADF; |
| 865 struct sockaddr_in* in_addr = (struct sockaddr_in*)addr; | 869 struct sockaddr_in* in_addr = (struct sockaddr_in*)addr; |
| 866 return socket_subsystem_->bind(&(GetFileHandle(sockfd)->stream), | 870 return socket_subsystem_->bind(&(GetFileHandle(sockfd)->stream), |
| 867 addr, addrlen); | 871 addr, addrlen); |
| 868 } | 872 } |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 959 | 963 |
| 960 while (!(IsReady(nfds, readfds, &Socket::is_read_ready, false) || | 964 while (!(IsReady(nfds, readfds, &Socket::is_read_ready, false) || |
| 961 IsReady(nfds, writefds, &Socket::is_write_ready, false) || | 965 IsReady(nfds, writefds, &Socket::is_write_ready, false) || |
| 962 IsReady(nfds, exceptfds, &Socket::is_exception, false))) { | 966 IsReady(nfds, exceptfds, &Socket::is_exception, false))) { |
| 963 SimpleAutoLock lock(select_mutex().get()); | 967 SimpleAutoLock lock(select_mutex().get()); |
| 964 if (timeout) { | 968 if (timeout) { |
| 965 if (!timeout->tv_sec && !timeout->tv_usec) | 969 if (!timeout->tv_sec && !timeout->tv_usec) |
| 966 break; | 970 break; |
| 967 | 971 |
| 968 if (select_cond().timedwait(select_mutex(), &ts_abs)) { | 972 if (select_cond().timedwait(select_mutex(), &ts_abs)) { |
| 969 if (errno == ETIMEDOUT) | 973 if (errno == ETIMEDOUT) { |
| 970 break; | 974 break; |
| 971 else | 975 } else { |
| 976 dbgprintf("select: timedwait problem %m\n"); | |
|
Evgeniy Stepanov
2012/06/15 12:31:47
missing an argument for %m
s/problem/error/
vissi
2012/06/15 13:03:20
%m means errno in glibc and does not require argum
Evgeniy Stepanov
2012/06/15 13:13:53
please make sure that newlib supports it, too
vissi
2012/06/18 08:35:09
Didn't find evidence for that in newlib docs, chan
| |
| 972 return -1; | 977 return -1; |
| 978 } | |
| 973 } | 979 } |
| 974 } else { | 980 } else { |
| 975 select_cond().wait(select_mutex()); | 981 select_cond().wait(select_mutex()); |
| 976 } | 982 } |
| 977 } | 983 } |
| 978 | 984 |
| 979 int nread = IsReady(nfds, readfds, &Socket::is_read_ready, true); | 985 int nread = IsReady(nfds, readfds, &Socket::is_read_ready, true); |
| 980 int nwrite = IsReady(nfds, writefds, &Socket::is_write_ready, true); | 986 int nwrite = IsReady(nfds, writefds, &Socket::is_write_ready, true); |
| 981 int nexcpt = IsReady(nfds, exceptfds, &Socket::is_exception, true); | 987 int nexcpt = IsReady(nfds, exceptfds, &Socket::is_exception, true); |
| 982 if (nread < 0 || nwrite < 0 || nexcpt < 0) { | 988 if (nread < 0 || nwrite < 0 || nexcpt < 0) { |
| 983 errno = EBADF; | 989 errno = EBADF; |
| 990 dbgprintf("select: EBADF problem %m\n"); | |
|
Evgeniy Stepanov
2012/06/15 12:31:47
see above
vissi
2012/06/15 13:03:20
here too.
| |
| 984 return -1; | 991 return -1; |
| 985 } | 992 } |
| 986 return nread + nwrite + nexcpt; | 993 return nread + nwrite + nexcpt; |
| 987 } | 994 } |
| 988 | 995 |
| 989 int KernelProxy::pselect(int nfds, fd_set *readfds, fd_set *writefds, | 996 int KernelProxy::pselect(int nfds, fd_set *readfds, fd_set *writefds, |
| 990 fd_set* exceptfds, const struct timeval *timeout, void* sigmask) { | 997 fd_set* exceptfds, const struct timeval *timeout, void* sigmask) { |
| 991 errno = ENOSYS; | 998 errno = ENOSYS; |
| 992 fprintf(stderr, "pselect has not been implemented!\n"); | 999 fprintf(stderr, "pselect has not been implemented!\n"); |
| 993 return -1; | 1000 return -1; |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 1009 | 1016 |
| 1010 int KernelProxy::getsockopt(int sockfd, int level, int optname, void *optval, | 1017 int KernelProxy::getsockopt(int sockfd, int level, int optname, void *optval, |
| 1011 socklen_t* optlen) { | 1018 socklen_t* optlen) { |
| 1012 errno = ENOSYS; | 1019 errno = ENOSYS; |
| 1013 fprintf(stderr, "getsockopt has not been implemented!\n"); | 1020 fprintf(stderr, "getsockopt has not been implemented!\n"); |
| 1014 return -1; | 1021 return -1; |
| 1015 } | 1022 } |
| 1016 | 1023 |
| 1017 int KernelProxy::setsockopt(int sockfd, int level, int optname, | 1024 int KernelProxy::setsockopt(int sockfd, int level, int optname, |
| 1018 const void *optval, socklen_t optlen) { | 1025 const void *optval, socklen_t optlen) { |
| 1019 errno = ENOSYS; | 1026 socket_subsystem_->setsockopt(GetFileHandle(sockfd)->stream, level, |
| 1020 fprintf(stderr, "setsockopt has not been implemented!\n"); | 1027 optname, optval, optlen); |
| 1021 return -1; | 1028 return 0; |
|
Evgeniy Stepanov
2012/06/15 12:31:47
why 0?
vissi
2012/06/15 13:03:20
Fixed.
| |
| 1022 } | 1029 } |
| 1023 | 1030 |
| 1024 int KernelProxy::shutdown(int sockfd, int how) { | 1031 int KernelProxy::shutdown(int sockfd, int how) { |
| 1025 FileHandle* fh = GetFileHandle(sockfd); | 1032 FileHandle* fh = GetFileHandle(sockfd); |
| 1026 if (fh == 0) | 1033 if (fh == 0) |
| 1027 return EBADF; | 1034 return EBADF; |
| 1028 return socket_subsystem_->shutdown(fh->stream, how); | 1035 return socket_subsystem_->shutdown(fh->stream, how); |
| 1029 } | 1036 } |
| 1030 | 1037 |
| 1031 int KernelProxy::socketpair(int domain, int type, int protocol, int sv[2]) { | 1038 int KernelProxy::socketpair(int domain, int type, int protocol, int sv[2]) { |
| 1032 errno = ENOSYS; | 1039 errno = ENOSYS; |
| 1033 fprintf(stderr, "socketpair has not been implemented!\n"); | 1040 fprintf(stderr, "socketpair has not been implemented!\n"); |
| 1034 return -1; | 1041 return -1; |
| 1035 } | 1042 } |
| 1036 | 1043 |
| OLD | NEW |