Home | History | Annotate | Download | only in nacl_io
      1 /* Copyright (c) 2013 The Chromium Authors. All rights reserved.
      2  * Use of this source code is governed by a BSD-style license that can be
      3  * found in the LICENSE file.
      4  */
      5 
      6 #include <errno.h>
      7 #include <poll.h>
      8 #include <pthread.h>
      9 #include <stdio.h>
     10 
     11 #include "nacl_io/error.h"
     12 #include "nacl_io/event_listener.h"
     13 #include "nacl_io/kernel_wrap.h"
     14 #include "nacl_io/osstat.h"
     15 #include "nacl_io/osunistd.h"
     16 
     17 #include "sdk_util/auto_lock.h"
     18 
     19 
     20 namespace nacl_io {
     21 
     22 EventListener::EventListener() {
     23   pthread_cond_init(&signal_cond_, NULL);
     24 }
     25 
     26 EventListener::~EventListener() {
     27   pthread_cond_destroy(&signal_cond_);
     28 }
     29 
     30 // Before we can destroy ourselves, we must first unregister all the
     31 // EventInfo objects from the various EventListeners
     32 void EventListener::Destroy() {
     33   EventInfoMap_t::iterator it;
     34 
     35   // We do not take the lock since this is the only reference to this object.
     36   for (it = event_info_map_.begin(); it != event_info_map_.end(); it++) {
     37     if (it->second->emitter) {
     38       it->second->emitter->UnregisterEventInfo(it->second);
     39     }
     40   }
     41 
     42   EventEmitter::Destroy();
     43 }
     44 
     45 uint32_t EventListener::GetEventStatus() {
     46   // Always writable, but we can only assume it to be readable if there
     47   // is an event waiting.
     48   return signaled_.empty() ? POLLOUT : POLLIN | POLLOUT;
     49 }
     50 
     51 int EventListener::GetType() {
     52   // For lack of a better type, report socket to signify it can be in an
     53   // used to signal.
     54   return S_IFSOCK;
     55 }
     56 
     57 // Called by EventEmitter, wakes up any blocking threads to verify if the wait
     58 // conditions have been met.
     59 void EventListener::Signal(const ScopedEventInfo& info) {
     60   AUTO_LOCK(signal_lock_);
     61   if (waiting_) {
     62     signaled_.insert(info);
     63     pthread_cond_broadcast(&signal_cond_);
     64   }
     65 }
     66 
     67 static void AbsoluteFromDeltaMS(struct timespec* timeout, int ms_timeout) {
     68   if (ms_timeout >= 0) {
     69     uint64_t usec = usec_since_epoch();
     70     usec += ((int64_t) ms_timeout * 1000);
     71 
     72     timeout->tv_nsec = (usec % 1000000) * 1000;
     73     timeout->tv_sec = (usec / 1000000);
     74   } else {
     75     timeout->tv_sec = 0;
     76     timeout->tv_nsec = 0;
     77   }
     78 }
     79 
     80 Error EventListener::Wait(EventData* events,
     81                           int max,
     82                           int ms_timeout,
     83                           int* out_count) {
     84   *out_count = 0;
     85 
     86   if (max <= 0)
     87     return EINVAL;
     88 
     89   if (NULL == events)
     90     return EFAULT;
     91 
     92   {
     93     AUTO_LOCK(info_lock_);
     94 
     95     // Go through the "live" event infos and see if they are in a signaled state
     96     EventInfoMap_t::iterator it = event_info_map_.begin();
     97     while ((it != event_info_map_.end()) && (*out_count < max)) {
     98       ScopedEventInfo& info = it->second;
     99       uint32_t event_bits = info->emitter->GetEventStatus() & info->filter;
    100 
    101       if (event_bits) {
    102         events[*out_count].events = event_bits;
    103         events[*out_count].user_data = info->user_data;
    104         (*out_count)++;
    105       }
    106 
    107       it++;
    108     }
    109   } // End of info_lock scope.
    110 
    111   // We are done if we have a signal or no timeout specified.
    112   if ((*out_count > 0) || (0 == ms_timeout))
    113     return 0;
    114 
    115   // Compute the absolute time we can wait until.
    116   struct timespec timeout;
    117   AbsoluteFromDeltaMS(&timeout, ms_timeout);
    118 
    119   // Keep looking if until we receive something.
    120   while (0 == *out_count) {
    121     // We are now officially waiting.
    122     AUTO_LOCK(signal_lock_);
    123     waiting_++;
    124 
    125     // If we don't have any signals yet, wait for any Emitter to Signal.
    126     while (signaled_.empty()) {
    127       int return_code;
    128       if (ms_timeout >= 0) {
    129         return_code = pthread_cond_timedwait(&signal_cond_,
    130                                              signal_lock_.mutex(),
    131                                              &timeout);
    132       } else {
    133         return_code = pthread_cond_wait(&signal_cond_, signal_lock_.mutex());
    134       }
    135 
    136       Error error(return_code);
    137 
    138       // If there is no error, then we may have been signaled.
    139       if (0 == error)
    140         break;
    141 
    142       // For any error case:
    143       if (ETIMEDOUT == error) {
    144         // A "TIMEOUT" is not an error.
    145         error = 0;
    146       } else {
    147         // Otherwise this has gone bad, so return EBADF.
    148         error = EBADF;
    149       }
    150 
    151       waiting_--;
    152       return error;
    153     }
    154 
    155     // Copy signals over as long as we have room
    156     while (!signaled_.empty() && (*out_count < max)) {
    157       EventInfoSet_t::iterator it = signaled_.begin();
    158 
    159       events[*out_count].events = (*it)->events;
    160       events[*out_count].user_data = (*it)->user_data;
    161       (*out_count)++;
    162 
    163       signaled_.erase(it);
    164     }
    165 
    166     // If we are the last thread waiting, clear out the signalled set
    167     if (1 == waiting_)
    168       signaled_.clear();
    169 
    170     // We are done waiting.
    171     waiting_--;
    172   }
    173 
    174   return 0;
    175 }
    176 
    177 Error EventListener::Track(int id,
    178                           const ScopedEventEmitter& emitter,
    179                           uint32_t filter,
    180                           uint64_t user_data) {
    181   AUTO_LOCK(info_lock_);
    182   EventInfoMap_t::iterator it = event_info_map_.find(id);
    183 
    184   // If it's not a streaming type, then it can not be added.
    185   if ((emitter->GetType() & (S_IFIFO | S_IFSOCK)) == 0)
    186     return EPERM;
    187 
    188   if (it != event_info_map_.end())
    189     return EEXIST;
    190 
    191   if (emitter.get() == this)
    192     return EINVAL;
    193 
    194   ScopedEventInfo info(new EventInfo);
    195   info->emitter = emitter.get();
    196   info->listener = this;
    197   info->id = id;
    198   info->filter = filter;
    199   info->user_data = user_data;
    200   info->events = 0;
    201 
    202   emitter->RegisterEventInfo(info);
    203   event_info_map_[id] = info;
    204   return 0;
    205 }
    206 
    207 Error EventListener::Update(int id, uint32_t filter, uint64_t user_data) {
    208   AUTO_LOCK(info_lock_);
    209   EventInfoMap_t::iterator it = event_info_map_.find(id);
    210   if (it == event_info_map_.end())
    211     return ENOENT;
    212 
    213   ScopedEventInfo& info = it->second;
    214   info->filter = filter;
    215   info->user_data = user_data;
    216   return 0;
    217 }
    218 
    219 Error EventListener::Free(int id) {
    220   AUTO_LOCK(info_lock_);
    221   EventInfoMap_t::iterator it = event_info_map_.find(id);
    222   if (event_info_map_.end() == it)
    223     return ENOENT;
    224 
    225   it->second->emitter->UnregisterEventInfo(it->second);
    226   event_info_map_.erase(it);
    227   return 0;
    228 }
    229 
    230 void EventListener::AbandonedEventInfo(const ScopedEventInfo& event) {
    231   {
    232     AUTO_LOCK(info_lock_);
    233 
    234     event->emitter = NULL;
    235     event_info_map_.erase(event->id);
    236   }
    237 
    238   // EventInfos abandoned by the destroyed emitter must still be kept in
    239   // signaled_ set for POLLHUP.
    240   event->events = POLLHUP;
    241   Signal(event);
    242 }
    243 
    244 }  // namespace nacl_io
    245