diff options
Diffstat (limited to 'hal/gonk/UeventPoller.cpp')
-rw-r--r-- | hal/gonk/UeventPoller.cpp | 312 |
1 files changed, 0 insertions, 312 deletions
diff --git a/hal/gonk/UeventPoller.cpp b/hal/gonk/UeventPoller.cpp deleted file mode 100644 index 3fbe850ed..000000000 --- a/hal/gonk/UeventPoller.cpp +++ /dev/null @@ -1,312 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* Copyright 2012 Mozilla Foundation and Mozilla contributors - * - * 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 <errno.h> -#include <fcntl.h> -#include <pthread.h> -#include <signal.h> -#include <string.h> -#include <strings.h> -#include <unistd.h> - -#include <arpa/inet.h> -#include <linux/types.h> -#include <linux/netlink.h> -#include <netinet/in.h> -#include <sys/socket.h> - -#include "HalLog.h" -#include "nsDebug.h" -#include "base/message_loop.h" -#include "base/task.h" -#include "mozilla/ClearOnShutdown.h" -#include "mozilla/FileUtils.h" -#include "mozilla/Monitor.h" -#include "nsThreadUtils.h" -#include "nsXULAppAPI.h" - -#include "UeventPoller.h" - -using namespace mozilla; - -namespace mozilla { -namespace hal_impl { - -static void ShutdownUevent(); - -class NetlinkPoller : public MessageLoopForIO::Watcher -{ -public: - NetlinkPoller() : mSocket(-1), - mIOLoop(MessageLoopForIO::current()) - { - } - - virtual ~NetlinkPoller() {} - - bool OpenSocket(); - - virtual void OnFileCanReadWithoutBlocking(int fd); - - // no writing to the netlink socket - virtual void OnFileCanWriteWithoutBlocking(int fd) - { - MOZ_CRASH("Must not write to netlink socket"); - } - - MessageLoopForIO *GetIOLoop () const { return mIOLoop; } - void RegisterObserver(IUeventObserver *aObserver) - { - mUeventObserverList.AddObserver(aObserver); - } - - void UnregisterObserver(IUeventObserver *aObserver) - { - mUeventObserverList.RemoveObserver(aObserver); - if (mUeventObserverList.Length() == 0) { - ShutdownUevent(); // this will destroy self - } - } - -private: - ScopedClose mSocket; - MessageLoopForIO* mIOLoop; - MessageLoopForIO::FileDescriptorWatcher mReadWatcher; - - const static int kBuffsize = 64 * 1024; - uint8_t mBuffer [kBuffsize]; - - typedef ObserverList<NetlinkEvent> UeventObserverList; - UeventObserverList mUeventObserverList; -}; - -bool -NetlinkPoller::OpenSocket() -{ - mSocket.rwget() = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); - if (mSocket.get() < 0) { - return false; - } - - int sz = kBuffsize; - - if (setsockopt(mSocket.get(), SOL_SOCKET, SO_RCVBUFFORCE, &sz, - sizeof(sz)) < 0) { - return false; - } - - // add FD_CLOEXEC flag - int flags = fcntl(mSocket.get(), F_GETFD); - if (flags == -1) { - return false; - } - flags |= FD_CLOEXEC; - if (fcntl(mSocket.get(), F_SETFD, flags) == -1) { - return false; - } - - // set non-blocking - if (fcntl(mSocket.get(), F_SETFL, O_NONBLOCK) == -1) { - return false; - } - - struct sockaddr_nl saddr; - bzero(&saddr, sizeof(saddr)); - saddr.nl_family = AF_NETLINK; - saddr.nl_groups = 1; - saddr.nl_pid = gettid(); - - do { - if (bind(mSocket.get(), (struct sockaddr *)&saddr, sizeof(saddr)) == 0) { - break; - } - - if (errno != EADDRINUSE) { - return false; - } - - if (saddr.nl_pid == 0) { - return false; - } - - // Once there was any other place in the same process assigning saddr.nl_pid by - // gettid(), we can detect it and print warning message. - HAL_LOG("The netlink socket address saddr.nl_pid=%u is in use. " - "Let the kernel re-assign.\n", saddr.nl_pid); - saddr.nl_pid = 0; - } while (true); - - if (!mIOLoop->WatchFileDescriptor(mSocket.get(), - true, - MessageLoopForIO::WATCH_READ, - &mReadWatcher, - this)) { - return false; - } - - return true; -} - -static StaticAutoPtr<NetlinkPoller> sPoller; - -class UeventInitTask : public Runnable -{ - NS_IMETHOD Run() override - { - if (!sPoller) { - return NS_OK; - } - if (sPoller->OpenSocket()) { - return NS_OK; - } - sPoller->GetIOLoop()->PostDelayedTask(MakeAndAddRef<UeventInitTask>(), - 1000); - return NS_OK; - } -}; - -void -NetlinkPoller::OnFileCanReadWithoutBlocking(int fd) -{ - MOZ_ASSERT(fd == mSocket.get()); - while (true) { - int ret = read(fd, mBuffer, kBuffsize); - if (ret == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { - return; - } - if (errno == EINTR) { - continue; - } - } - if (ret <= 0) { - // fatal error on netlink socket which should not happen - _exit(1); - } - NetlinkEvent netlinkEvent; - netlinkEvent.decode(reinterpret_cast<char*>(mBuffer), ret); - mUeventObserverList.Broadcast(netlinkEvent); - } -} - -static bool sShutdown = false; - -class ShutdownNetlinkPoller; -static StaticAutoPtr<ShutdownNetlinkPoller> sShutdownPoller; -static Monitor* sMonitor = nullptr; - -class ShutdownNetlinkPoller { -public: - ~ShutdownNetlinkPoller() - { - // This is called from KillClearOnShutdown() on the main thread. - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(XRE_GetIOMessageLoop()); - - { - MonitorAutoLock lock(*sMonitor); - - XRE_GetIOMessageLoop()->PostTask( - NewRunnableFunction(ShutdownUeventIOThread)); - - while (!sShutdown) { - lock.Wait(); - } - } - - sShutdown = true; - delete sMonitor; - } - - static void MaybeInit() - { - MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop()); - if (sShutdown || sMonitor) { - // Don't init twice or init after shutdown. - return; - } - - sMonitor = new Monitor("ShutdownNetlinkPoller.monitor"); - { - ShutdownNetlinkPoller* shutdownPoller = new ShutdownNetlinkPoller(); - - nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([=] () -> void - { - sShutdownPoller = shutdownPoller; - ClearOnShutdown(&sShutdownPoller); // Must run on the main thread. - }); - MOZ_ASSERT(runnable); - MOZ_ALWAYS_SUCCEEDS( - NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL)); - } - } -private: - ShutdownNetlinkPoller() = default; - static void ShutdownUeventIOThread() - { - MonitorAutoLock l(*sMonitor); - ShutdownUevent(); // Must run on the IO thread. - sShutdown = true; - l.NotifyAll(); - } -}; - -static void -InitializeUevent() -{ - MOZ_ASSERT(!sPoller); - sPoller = new NetlinkPoller(); - sPoller->GetIOLoop()->PostTask(MakeAndAddRef<UeventInitTask>()); - - ShutdownNetlinkPoller::MaybeInit(); -} - -static void -ShutdownUevent() -{ - sPoller = nullptr; -} - -void -RegisterUeventListener(IUeventObserver *aObserver) -{ - MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop()); - - if (sShutdown) { - return; - } - - if (!sPoller) { - InitializeUevent(); - } - sPoller->RegisterObserver(aObserver); -} - -void -UnregisterUeventListener(IUeventObserver *aObserver) -{ - MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop()); - - if (sShutdown) { - return; - } - - sPoller->UnregisterObserver(aObserver); -} - -} // hal_impl -} // mozilla - |